精华内容
下载资源
问答
  • String类不可变以及不可变类总结

    千次阅读 2017-10-01 20:11:38
    String类在java中是immutable(不可变),因为它被关键字final修饰。当String实例创建时就会被初始化,并且以后无法修改实例信息。String类是工程师精心设计的艺术品。 一、String为什么不可变? 要了解String类...

          String类在java中是immutable(不可变),因为它被关键字final修饰。当String实例创建时就会被初始化,并且以后无法修改实例信息。String类是工程师精心设计的艺术品。

    一、String为什么不可变?

           要了解String类创建的实例为什么不可变,首先要知道final关键字的作用:final的意思是“最终,最后”。final关键字可以修饰类、方法、字段。修饰类时,这个类不可以被继承;修饰方法时,这个方法就不可以被覆盖(重写),在JVM中也就只有一个版本的方法--实方法;修饰字段时,这个字段就是一个常量。

            查看java.lang.String方法时,可以看到:

    /**
     * The String class represents character strings. All string literals in Java programs, such as "abc",
     * are implemented as instances of this class.
    */
    public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
        private final char value[];
       ...
    }

    "The String class represents character strings"意思是String类表示字符串;String类被关键字final修饰,可以说明它不可被继承;从"private final char value[]"可知,String本质上是一个char数组

            String类的成员字段value是一个char[]数组,而且也是用final关键字修饰,被final关键字修饰的字段在创建后其值是不可变的,但也只是value这个引用地址不可变,可是Array数组的值却是可变的,Array数组数据结构如下图所示:

    从图中可以看出,Array变量只是栈上(stack)的一个引用,数组中的数据存储在堆上(heap)。String类里的value是用final修饰,只能说在栈上(stack)这个value的引用地址不可变,可没说堆里的Array本身数据不可变。看下面这个例子:

    final int[] value = {1,2,3,4,5};
    int otherValue = {6,7,8,9,10};
    value = otherValue;//编译报错

    value是被final关键字修饰的,编译器不允许把value指向堆另外一个地址;但如果直接对数组元素进行赋值,就允许;如下面这个例子:

    final int[] value  = {1,2,3,4,5};
    value[0] = 0;

            所以说String是不可变,在后面所有的String方法里没有去动Array中的元素,也没有暴露内部成员字段。private  final char value[],private的私有访问权限的作用都比final大。所以String是不可变的关键都是在底层实现的,而不是一个简单的final关键字。

    二、String类实例不可变的内存结构图

            String类实例不可变很简单,如下图所示是String类实例不可变的内存结构图:

     

    有一个字符串s的值为"abcd",它再次被赋值为"abcdef",不是在原堆的地址上修改数据,而是重新指向一个新的对象,新的地址。

    三、字符串常量池

            字符串常量池是方法区(Method Area)中一个特殊的存储区域。当一个字符串被创建时,如果这个字符串的值已经存在String pool中,就返回这个已经存在的字符串引用,而不是创建一个新的对象。下面的代码只会在堆中创建一个对象:

    String name="abcd";
    String userName="abcd";

    这样在大量使用字符串的情况下,可以节省内存空间,提高效率。但之所以能实现这个特性,String的不可变性是最基础的一个必要条件。

    四、String类不可变有什么好处?

        最简单的就是为了安全和效率。从安全上讲,因为不可变的对象不能被改变,他们可以在多个线程之间进行自由共享,这消除了进行同步的要求;从效率上讲,设计成final,JVM才不用对相关方法在虚函数表中查询,而是直接定位到String类的相关方法上,提高执行效率;总之,由于效率和安全问题,String被设计成不可变的,这也是一般情况下,不可变的类是首选的原因。

    五、不可变类

            不可变类只是它的实例不能被修改的类。每个实例中包含的所有信息都必须在创建该实例时就提供,并在对象 的整个生命周期内固定不变。String、基本类型的包装类、BigInteger和BigDecimal就是不可变得类。

            为了使类成为不可变,必须遵循以下5条规则:①不要提供任何会修改对象状态的方法②保证类不会被扩展③使所有的域都是final④使所有的域都成为私有的⑤确保 对于任何可变组件的互斥访问。如果类具有指向可变对象的域,则必须确保该类的客户端无法获得指向这些对象的引用。

    六、不可变类的优点和缺点

            不可变类实例不可变性,具有很多优点。①不可变类对象比较简单。不可变对象可以只有一种状态,即被创建时的状态。②不可变对象本质上是线程安全的,它们不要求同步。当多个线程并发访问这样的对象时,它们不会遭到破坏。实际上,没有任何线程会注意到其他线程对于不可变对象的影响。所以,不可变对象可以被自由地分配。“不可变对象可以被自由地分配”导致的结果是:永远不需要进行保护性拷贝。③不仅可以共享不可变对象,甚至也可以共享它们的内部信息。④不可变对象为其他对象提供了大量的构件。如果知道一个复杂对象内部的组件不会改变,要维护它的不变性约束是比较容易的。

            不可变类真正唯一的缺点是,对于每个不同的值都需要一个单独的对象。创建这种对象的代价很高。

    七、如何构建不可变类?

            构建不可变类有两种方式:用关键字final修饰类让类的所有构造器都变成私有的或者包级私有的,并添加公有的静态工厂来替代公有的构造器

            为了具体说明用静态工厂方法来替代公有的构造器,下面以Complex为例:

    //复数类
    public class Complex{
        //实数部分
        private final double re;
        //虚数部分
        private final double im;
        //私有构造器
        private Complex(double re,double im){
            this.re = re;
            this.im = im;
        }
        //静态工厂方法,返回对象唯一实例
        public static Complex valueOf(double re,double im){
            return new Complex(re,im);
        }
        ...
    }

          不可变的类提供一些静态工厂方法,它们把频繁请求的实例缓存起来,从而当现在实例符合请求的时候,就不必创建新的实例。使用这样的静态工厂方法使得客户端之间可以共享现有的实例,而不是创建新的实例,从而减低内存占用和垃圾回收的成本。

           总之,使类的可变性最小化。不要为每个get方法编写一个相对应的set方法,除非有很好的理由要让类成为可变的类,否则就应该是不可变的。如果有些类不能被做成是不可变的,仍然应该尽可能地限制它的可变性。不可变的类有很多优点,但唯一的缺点就是在特定的情况下存在潜在的性能问题。

     

    PS:静态工厂方法是什么?

    静态工厂方法只是一个返回类的实例的静态方法,如下面是一个Boolean的简单实例。这个方法将boolean基本类型值转换成一个Boolean对象引用。

    public static Boolean valueOf(boolean b){
        return b?Boolean.TRUE?Boolean.FALSE;
    }

    静态工厂方法相对于构造器来说,具有很多优势:

     

    创建的方法有名字

    不必在每次调用它们的时候都创建一个新的对象

    可以返回原返回类型的任何子类的对象。这样我们在选择返回对象的类时就有更大的灵活性,这种灵活性的一种应用是API可以返回对象,同时又不会使对象的类变成公有的。以这种方式隐藏实现类会使API变得非常简洁,这项技术适用于基于接口的框架。

    在创建参数化类型实例时,它们使代码变得更加简洁。编译器可以替你找到类型参数,这被称为类型推导。如下面这个例子

    public static<k,v> HashMap<k,v> newInstance(){
        return new HashMap<k,v>();
    }

    静态工厂方法也有缺点:

    类如果不含公有的或者受保护的构造器,就不能被子类化。对于公有的静态工厂方法所返回的非公有类也同样如此。

    它们与静态方法实际上没有什么区别

    简而言之,静态工厂方法和公有构造器都各有用处,我们需要理解它们各自的长处。结合实际情况,再做选择。

     

     

    参考文章:Why String is immutable in Java?

                      在java中String类为什么要设计成final?程序员--知乎

    展开全文
  • JAVA - 可变对象与不可变对象

    千次阅读 2018-06-14 18:34:08
    不可变对象在并发程序中比较有用,由于其状态无法改变,因此无法被线程的干扰损坏或者被视为不一致状态。基本概念 *不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能...

    不可变对象在并发程序中比较有用,由于其状态无法改变,因此无法被线程的干扰损坏或者被视为不一致状态。

    基本概念   

    *不可变对象(Immutable Objects)即对象一旦被创建它的状态(对象的数据,也即对象属性值)就不能改变,任何对它的改变都应该产生一个新的对象

    * 可变对象(Mutable Objects):相对于不可变类,可变类创建实例后可以改变其成员变量值,开发中创建的大部分类都属于可变类

    * 不可变对象的类即为不可变类(Immutable Class)。JAVA平台类库中包含许多不可变类,如String、基本类型的包装类、BigInteger和BigDecimal等。

    编写不可变类

    可以遵照以下几点来编写一个不可变类:

    A. 确保类不能被继承将类声明为final, 或者使用静态工厂并声明构造器为private。如果类可以被继承会破坏类的不可变性机制,只要继承类覆盖父类的方法并且继承类可以改变成员变量值,那么一旦子类以父类的形式出现时,不能保证当前类是否可变。

    B. 使用private和final修饰符来修饰该类的属性

    注:如果成员属性为变对象属性,不要使这些对象改变:

    1)不要提供更改可变对象的方法

    2)不要共享对可变对象的引用,不要存储传给构造器的外部可变对象的引用。因为引用可变对象的成员变量和外部可变对象的引用指向同一块内存地址,用户可以在不可变类之外通过修改可变对象的值

    public final class ImmutableDemo {  
        private final int[] myArray;  
        public ImmutableDemo(int[] array) {  
            this.myArray = array; // wrong  
        }  
    }

    为了保证内部的值不被修改,可以采用深度拷贝的方法来复制一个对象并传入副本的引用来确保类的不可变

    public final class MyImmutableDemo {  
        private final int[] myArray;  
        public MyImmutableDemo(int[] array) {  
            this.myArray = array.clone();   
        }   
    }

    有必要时类中的方法返回内部可变对象的副本而不是原对象

    C. 不要提供任何可以修改对象状态的方法不仅仅是set方法, 还有任何其它可以改变状态的方法

    举个例子:

    import java.util.Date;
    
    public final class Planet {
        //声明为final的基本类型数据总是不可变的
        private final double fMass;
        //不可变的对象属性 (String对象不可变)
        private final String fName;
        //可变对象的属性,因为可变属性只能被这个类改变,采用深度拷贝的方法来复制一个对象并传入副本的引用
        private final Date fDateOfDiscovery;
        
        public Planet(double aMass, String aName, Date aDateOfDiscovery) {
            fMass = aMass;
            fName = aName;
            //创建aDateOfDiscovery的一个私有拷贝
            //这是保持fDateOfDiscovery属性为private的唯一方式, 并且保护这个
            //类不受调用者对于原始aDateOfDiscovery对象所做任何改变的影响
            fDateOfDiscovery = new Date(aDateOfDiscovery.getTime());
        }
        //返回一个基本类型值.
        public double getMass() {
            return fMass;
        }
        //调用者得到内部属性的一个直接引用. 由于String是不可变的所以没什么影响
        public String getName() {
            return fName;
        }
        //返回一个可变对象的一个保护性拷贝.调用者可以任意改变返回的Date对象,但是不会
        //影响类的内部.为什么? 因为它们没有fDate的一个引用. 更准确的说, 它们
        //使用的是和fDate有着相同数据的另一个Date对象
        public Date getDateOfDiscovery() {
            return new Date(fDateOfDiscovery.getTime());
        }
    
        public static void main(String[] args) {
        	Planet planet = new Planet(1.0D, "earth", new Date());
        	Date date = planet.getDateOfDiscovery();
        	date.setTime(111111111L);
        	System.out.println("the value of fDateOfDiscovery of internal class : " + planet.fDateOfDiscovery.getTime());
        	System.out.println("the value of date after change its value : " + date.getTime());
    	}
    }

    运行结果:

    the value of fDateOfDiscovery of internal class : 1393943752205
    the value of date after change its value : 111111111

    不可变对象的优缺点

    优点

    * 构造、测试和使用都很简单

    * 不可变对象是线程安全的,在线程之间可以相互共享,不需要利用特殊机制来保证同步问题,因为对象的值无法改变。可以降低并发错误的可能性,因为不需要用一些锁机制等保证内存一致性问题也减少了同步开销。

    * 不可变对象可以被重复使用,可以将它们缓存起来重复使用,就像字符串字面量和整型数字一样。可以使用静态工厂方法来提供类似于valueOf()这样的方法,它可以从缓存中返回一个已经存在的Immutable对象,而不是重新创建一个。

    public class CacheImmutale {  
        private final String name;  
        private static CacheImmutale[] cache = new CacheImmutale[10];  
        private static int pos = 0;  
      
        public CacheImmutale(String name) {  
            super();  
            this.name = name;  
        }  
      
        public String getName() {  
            return name;  
        }  
      
        public static CacheImmutale valueOf(String name) {  
            // 遍历已缓存的对象  
            for (int i = 0; i < pos; i++) {  
                // 如果已有相同实例,直接返回该缓存的实例  
                if (cache[i] != null && cache[i].getName().equals(name)) {  
                    return cache[i];  
                }  
            }  
            // 如果缓冲池已满  
            if (pos == 10) {  
                // 把缓存的第一个对象覆盖  
                cache[0] = new CacheImmutale(name);  
                pos = 1;  
                return cache[0];  
            } else {  
                // 把新创建的对象缓存起来,pos加1  
                cache[pos++] = new CacheImmutale(name);  
                return cache[pos - 1];  
            }  
        }  
      
        @Override  
        public int hashCode() {  
            return name.hashCode();  
        }  
      
        @Override  
        public boolean equals(Object obj) {  
            if (obj instanceof CacheImmutale) {  
                CacheImmutale ci = (CacheImmutale) obj;  
                if (name.equals(ci.getName())) {  
                    return true;  
                }  
            }  
            return false;  
        }  
      
        public static void main(String[] args) {  
            CacheImmutale c1 = CacheImmutale.valueOf("hello");  
            CacheImmutale c2 = CacheImmutale.valueOf("hello");  
            System.out.println(c1 == c2);// 输出结果为true  
        }  
    }

    缺点:

    * 不可变对象最大的缺点就是创建对象的开销,因为每一步操作都会产生一个新的对象,制造大量垃圾,由于他们不能被重用而且对于它们的使用就是”用“然后”扔“,会创造很多的垃圾,给垃圾收集带来很大的麻烦

    展开全文
  • 一本书上关于有限元和边界元的比较,摘录如下:有限元基于区域上的变分原理和剖分插值,边界元基于边界归化及边界上的剖分插值;有限元属于区域法,其剖分涉及到整个区域,而边界元只需对边界离散,因此,可以降低...
    


    一本书上关于有限元和边界元的比较,摘录如下:有限元基于区域上的变分原理和剖分插值,边界元基于边界归化及边界上的剖分插值;有限元属于区域法,其剖分涉及到整个区域,而边界元只需对边界离散,因此,可以降低求解问题的维数;有限元法待求未知数多,要求解的方程规模大,导致输入数据多,计算的准备工作量大,边界元法则相对规模小一些;有限元必须同时对所有域内节点和边界节点联立求解,边界元只需对边界节点联立求解,然后可以相互独立、完全并行的计算域内各点的函数值;有限元的系数矩阵带状稀疏,且保持对称正定性,边界元法的矩阵为满矩阵,一般不能保证正定对称性;有限元适应复杂的几何形状和边界条件,适于求解非线性、非匀质问题,边界元仅适应规则区域及边界条件,适于求解线性、匀质问题;有限元适合于求解有界区域无奇异性问题,而边界元适合于求无界区域问题及若干奇异性问题;对于狭长区域,有限元的精度高于边界元,其它情况下,边界元的精度较高。

    1、边界元方法使问题的维数降低一维,例如:三维问题变为二维问题,二维变成一维问题。使得解题的自由度下降。
    2、边界元相对于有限元来说,在相同离散精度的条件下,边界元解的精度要高于有限元。
    3、边界元方法在有些情况下,可以较容易地处理有限元方法很难处理的问题,例如,无限域问题,断裂问题等。
    4、在问题的规模(自由度)不大的情况下,边界元的解题速度高于有限元方法。但是,由于边界元方法形成的线性方程组的系数矩阵是满阵,所以在处理大规模问题时遇到了困难,解题的规模受到限制。适合于处理中小规模问题。
    5、边界元适合于处理位势问题、弹性问题,而在处理弹塑性问题或大的有限变形问题时,由于需要对物体进行体积离散,此时,边界元降维的优点消失。所以会在处理这一类问题时遇到一些困难。
    6、边界元相对于有限元来说,其软件的商业化程度远不如有限元。所以,其处理问题时,一般是针对某一问题专门编制程序进行计算。其前、后处理的工作量较大。
    7、边界元方法解题需要求出问题的基本解,基本解的推导一般比较复杂。通过许多学者的努力对于一些问题,基本解已经被推导出来,但是,对于某些问题,问题的基本解很难求出。

    二者的耦合起来解决问题还是有人做的,尤其是模拟半无限空间体时一般用有限元对分析域内部进行求解,而在边界上采用边界元,这在二维、三维波动问题数值模拟中还是较为常用的吧。这正是充分地发挥两者的优势。利用有限元适合于解决大规模问题和边界元适合于解决无限域问题和解的精度高的特点,来更好地解决实际问题!对于有些问题,用两者耦合的方法是比较好的!

    推荐几本边界元论著:堪称经典的还是老布的那本 The Boundary Element Method for Engineers,有中文译本,算是国内较早的边界元入门书籍了,中文名称:《工程师用的边界元法》C.A.Brebbia 科学出版社1986.7 布莱比亚先生现在在英国主持一个学术刊物,国内不少文章都投向那边。

     

    数值计算方法介绍

     

    1、有限差分法(Finite difference method,FDM)

       这是求得偏微分方程数值解的最古老方法,对简单的几何形状中的流动与传热问题也是一种最容易实施的方法、其基本的实施方法是,将求解区域用网格线的交点(节点)所组成的点的几何来代替,在每个节点上,描述所研究的流动与传热问题的偏微分方程中的每一个导数项用相应的差分表达式来代替,从而在每个节点上形成一个代数方程,其中包含了本节点及其附近一些节点上的所求量的未知值。求解这些代数方程组就获得了所需的数值解。在规则区域的结构化网格上,有限差分法是十分简单而有效的,而且很容易引入对流项的高阶格式。其不足的是离散方程的守恒特性难以保证,而最严重的缺点则是对不规则区域的适应性差。

    2、有限容积法(Finite volume method,FVM)

       有限容积法从描述流动与传热问题的守恒型控制方程出发,对它在控制容积上作积分,在积分过程中需要对界面上被求函数的本身(对流通量)及其一阶导数的(扩散通量)构成方式作出假设,这就形成了不同的格式。由于扩散项多是采用相当于二阶精度的线性插值,因而格式的区别主要表现在对流项上。用有限容积法导出的离散方程可以保证具有守恒性(只要界面上的插值方法对位于界面两侧的控制容积式一样的即可),对区域形状的适应性也比有限差分法要好。是目前应用最普遍的一种数值方法。

    3、有限元法(Finite element method,FEM)

       有限元法中把计算区域划分成一组离散的容积或者叫元体(在二维情形下元件的形状常常是三角形或者四边形),然后通过对控制方程作积分来得出离散方程,它与有限容积法的主要区别在于:

       (1)对每个元体要选定一个形状函数(最简单的为线性函数),通过元件中节点上的被求变量之值来表达该形状函数,并在积分之前把所有假设的形状函数带入到控制方程中去;

       (2)控制方程在积分之前应乘上一个选定的权函数,并要求在整个区域上控制方程余量的加权平均值为零,从而导出一组关于节点上被求变量的代数方程。

        有限元法的最大优点是,对于不规则几何区域的适应性好。有限元法在对流项的离散处理及不可压缩Naver0-Stokes方程的原始变量法求解方面不如有限容积法发展成熟。但随着有线容积法中非结构化网格的应用,有限容积法与有限差分法之间的差别正在缩小中。

    4、有限分析法(Finite analytic method,FAM)

       在有限分析法中也像有限差分法、有限容积法那样,用一系列网格线将计算区域进行离散,所不同的是在这里每个节点(网格的交点)与其相邻的四个网格(二维问题)组成一个计算单元,即每一个计算单元由一个内点及八个邻点所组成。在计算单元内把控制方程的非线性项(如N-S方程中的对流项)局部线性化(即认为流速已知),并对该单元边界上未知函数的变化型线作出假设,把所选型线表达式中的常数或者系数用单元边界节点的函数来表示。这样在该单元内的被求解问题转化成了第一类边界条件下的问题,设法找出其分析解,并利用这一分析解找出该单元的内节点及其八个邻点上未知函数值之间的代数表达式,这就是该内点的离散方程。逐一对求解区域的每一个节点建立离散方程,并对计算区域边界上不是第一类条件的每节点补充一个方程,就完成了整个计算区域的离散方程的建立过程。

        有限分析法是80年代初发展起来的一种数值方法,它可以克服高Reynolds数下有限差分法及有限容积法的数值解容易发散或振荡的缺点,但其计算工作量较大,对计算区域几何形状的适应性也较差。

    5、边界元法(Boudary element method,BEM)

       上面四种方法都必须对整个区域作离散化处理,用分布在整个区域上的有限个节点上函数的近似值来代替连续问题的解。在边界元方法中应用格林函数公式,并通过选择适当的权函数把空间求解域上的偏微分方程转换成为其边界上的积分方程,它把求解区中任一点的求解变量(如温度)与边界条件联系了起来,通过离散化处理,由积分方程导出边界节点上未知值的代数方程。解出边界上的未知值后就可以利用边界积分方程来获得内部任一点的被求函数之值。边界元法的最大优点是,可以使求解问题的空间维数降低一阶,从而使计算工作量及其所需计算机容量大大减小,边界元法推广应用的一个最大限制是,需要已知所求解偏微分方程的格林函数基本解,虽然对不少偏微分方程这个基本解业已找出,但对Navier-Stokes方程这个非线性偏微分方程,至今尚未找到基本解。目前的一种处理方式是,把Navier-Stokes方程中的非线性项看作是扩散方程的源项并通过迭代的方式来求解,但一般只能获得Re较低情形的解。

    6、谱分析法(Spectral method,SM)

       在谱方法中被求解的函数用有限项的级数展开来表示。例如,有限项的傅里叶展开,多项式展开等。显然,只要这种级数中每一项的系数一确定,这个被求解的函数的近似形式也就完全确定了。因而与前面五种离散方法不同的是,在谱方法中要建立的代数方程式关于这些系数的代数方程,而不是节点上被求解函数值的代数方程。显然,级数的项越多,其精度也越高。建立未知系数的代数方程的基本方法是加权余数法,即首先将近似解带入控制方程(设控制方程中所有的项均移到了等号左边),再乘以近似解级数中的一个项称为权函数(不包括该项中待定的系数),然后对整个求解区域作积分,并要求该积分式等于零,就得出一个关于待定系数的代数方程,这样以系数解中每一个含有待定系数的项作权函数,就可以得到总数与待定系数数量相等的代数方程组。求解方程组,就得出了被求解函数的近似解。

       谱分析法用于偏微分方程的近似求解始于20世纪70年代末,其优点是可以获得高精度的解,但不适宜用于编制通用程序,目前只是在比较简单的流动与传热问题中已经应用的比较成功。

    7、数值积分变换法(Integral transformation method,ITM)

       我们知道在偏微分方程的分离变量法求解中,一个被求函数表示了两个特征值问题所规定的特征函数乘积的线性组合。一般地说,任意一个函数可用相应的特征值问题的特征函数来表示。对不具备分析解的非线性偏微分方程,设法把它的解表示成一个特征值问题的解及一个降维的定解问题解的组合:其中特征值问题具有分析解,而定解问题则应包含该问题的诸多非线性复杂因素,因而要采用数值解法,这就是数值积分变换法。由于该定解问题降低了维数(常常变为常微分方程的初值问题或者两点边值问题),因而数值求解比较方便,这一方法是分析解法与数值解法的混合方法。对于数值解问题而言,只需要得出某个降维了的空间内(对二维问题或者是时间坐标或者是某个空间坐标)的数值解,整个求解区域内的值则可以用分析解与数值解的组合来得到。在获得降维的定解问题过程中需要进行积分变换与反变换,而该降维问题的求解是采用数值方法的,因而称其为数值积分变换法。这一方法的优点是计算精度可以较高,降维问题是一个常微分方程,有成熟的数值方法可以采用,但这种方法不容易形成通用程序,特征值问题的选取有一定的任意性,对非线性强烈的问题,计算工作量比较大。

    8、格子-Boltzmann方法(Lattice-Boltzmann method,LBM)

       格子-Boltzmann方法是基于分子运动论的一种模拟流体流动的数值方法。在上述各种数值方法中,把本质上市离散的介质先假定是连续的,在此基础上建立起了N-S方法,然后又再把它离散化。在LMB中不再基于连续介质的假设,而是把流体看成是许多只有质量没有体积的微粒所组成,这些微粒可以向空间若干个方向任意运动。通过其质量、动量守恒的原理,建立起表征质点在给定的时刻位于空间某一位置附近的概率密度函数。再通过统计的方法来获得质

    展开全文
  • 今天在用springboot框架开发用户管理模块 合代码的时候的时候,由于之前地实体类中id定义的...但是现在问题就出来了,值在本应该相等的地方进入相等体系中的逻辑,但却进入了相等的逻辑流程中。 最后发现是int和In...

    今天在用springboot框架开发用户管理模块 合代码的时候的时候,由于之前地实体类中id定义的是int类型, 而mybatis中自动生成的是Integer类型的,为了统一代码,都改成了Integer类型的。之前我的模块所有的数据(就是当时数据类型还是int)都测过,都没问题。
    但是现在问题就出来了,值在本应该相等的地方进入相等体系中的逻辑,但却进入了不相等的逻辑流程中。
    最后发现是int和Integer类型不匹配的原因。
    在用两个Integer对象比较数值的话,如果是整型值的话最好调用intValue方法来得到一个int类型的值,当然也可将其转变为
    float(floatValue),double(longValue)类型来比较。

    public int intValue() 以 int 类型返回该 Integer 的值。

    指定者:类 Number 中的 intValue返回:转换为 int 类型后该对象表示的数值。
    下面以一个例子详细说明:

    /**
     * 测试 两个Integer类型的值相比较的问题
     * 当给Integer直接赋值时,如果在-128到127之间相等的话,它们会共用一块内存,
     * 而超过这个范围,则对应的Integer对象有多少个就开辟多少个
     */
    public class ClassD {
        public static void main(String[] args) {
    
            // 两个new出来的Integer类型的数据比较,相当于把new出来的地址作比较
            Integer a0 = new Integer(1);// 普通的堆中对象
            Integer b0 = new Integer(1);
            System.out.println("new出来的 " + "a0==b0 :" + (a0 == b0));
            System.out.println("a0:"+a0+" b0:"+b0);
    
            // 调用intValue方法得到其int值
            System.out.println("调用intValue " + "a0.intValue() == b0.intValue() " +
                    (a0.intValue() == b0.intValue()));
    
            // 把Integer类型的变量拆箱成int类型
            int c = 1;
            System.out.println("将Integer自动拆箱 " + "a0==c: " + (a0 == c));
    
            // 其实也是内存地址的比较
            Integer a1 = 30; // 自动装箱,如果在-128到127之间,则值存在常量池中
            Integer b1 = 30;
            System.out.println("直接赋值的两个Integer类型的比较 " +
                    "a1 == b1: "+ (a1 == b1));
    
    
            Integer a3 = 128;
            Integer b3 = 128;
            System.out.println("直接赋值的两个Integer类型的比较 " +
                    "a3 == b3: " + (a3 == b3));
    
            Integer a4 = 412;
            Integer b4 = 412;
            System.out.println("直接赋值的两个Integer类型的比较 " +
                    "a4 == b4: " + (a4 == b4));
    
            System.out.println("调用intValue " + "a4.intValue() == b4.intValue(): "
                    + (a4.intValue() == b4.intValue()));
        }
    }
    
    

    控制台打印的结果如下图所示:
    在这里插入图片描述

    展开全文
  • 在这篇文章中,我们将讨论Hadoop 2.x与Hadoop 3.x之间的比较。 Hadoop3版本中添加了哪些新功能,Hadoop3中兼容的Hadoop 2程序,Hadoop 2和Hadoop 3有什么区别? 我们希望Hadoop 2和Hadoop 3之间的这个功能的区别将...
  • 滞回比较器一、滞回比较器原理二、电路设计三、仿真结果合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右...
  • MySQL脏读、不可重复读、幻读

    千次阅读 2018-08-18 17:38:43
    原子性:指处于同一个事务中的多条语句是不可分割的。 一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账,转账前两个账户余额之和为2k,转账之后也应该是2K。 隔离性:指多线程环境下...
  • 字符串(与数组进行比较

    千次阅读 2019-01-22 22:15:49
    JavaScript中的字符串和数组都是类数组(类数组就是包含有length属性,常见的是函数中的arguments的对象以及DOM方法返回的结果)。...二、与数组的不同点在js中,字符串是不可变的(可参考 链接描述 ),而...
  • 偶然看到一个问题,顺便总结一下std::...std::string 字符串可以初始化为NULL,虽然能通过编译,但是会出现运行错误。 std::string 使用以下两种初始化为空的方式:std::string s;//执行默认构造函数 std::string s
  • 可数集合与不可数集合

    万次阅读 多人点赞 2015-07-22 00:16:30
    集合,set,就是将一些确定的东西...对于 S 中的元素 a,me 们说 a ∈ S (a 属于 S),当然如果 a 在 S 中,me 们就说 a ∉ S (a 属于 S)。 集合中元素的个数,有时候是有限 (finit) 的,有时候不是有限的,比如 {
  • 摘要 python中的字典类似于js中的json,其实就...python中的集合,可以和列表相比较,因为它们只存储key,而存储value,但是列表有序而集合无序。同时它还可以和字典比较,因为集合和字典的实现方式一样,原因是在集
  • 收藏 |7本 Matlab入门经典教程书籍,不可错过! Matlab的教程琳琅满目,一不小心就选的眼花缭乱。 选择Matlab参考书最关键的一点,就是参考书和自己目前能力要匹配。选的参考书过于简单或过于困难,既浪费钱,又...
  • 原子性:指处于同一个事务中的多条语句是不可分割的。 一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账,转账前两个账户余额之和为2k,转账之后也应该是2K。 隔离性:指多线程环境下,...
  • Matlab的教程琳琅满目,一小心就选的眼花缭乱。...第一本:《Matlab经典教程—从入门到精通》这本教程比较适合真正一点也懂的初学者,它有这样三个优点:(1) 概念讲的很清楚。(2) 命令归纳的全面。(3) 对照...
  • 忽略大小写比较字符串大小

    千次阅读 2015-10-11 17:31:29
    一般我们用strcmp比较两个字符串的大小,比较方法为对两个字符串从前往后逐个字符相比较(按ASCII码值大小比较),直到出现不同的字符或遇到’\0’为止。如果全部字符都相同,则认为相同;如果出现相同的字符,...
  • 事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都做 2 、一致性 (Consistency) 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,...
  • 为以后留个备用吧,博主最近在用七牛云存储,虽然有10G免费空间但每个月有10G的流量限制,敢放太多图片,只把一些重要图片放在上面,其他的基本上都是放在新浪微博图床上面的。 什么是图床? ...
  • linux下的三种执行文件格式的比较

    千次阅读 2008-10-25 15:38:00
    本文讨论了 UNIX/LINUX 平台下三种主要的执行文件格式:a.out(assembler and link editor output汇编器和链接编辑器的输出)、COFF(Common Object File Format 通用对象文件格式)、ELF(Executableand Linking ...
  • Python:比较两个dataframe是否相等

    万次阅读 2019-10-17 11:13:03
    别写df1 == df2(这是逐个元素相比较)。 要写assert_frame_equal。不仅能比较两个df是否相等,还能告诉你哪里一样。 assert_frame_equal是比较两个df是否完全一模一样。index都要一样! import pandas as pd ...
  • IPv4 与 IPv6 的比较

    万次阅读 多人点赞 2018-06-30 09:22:52
    IPv4地址长度:32位地址数量:2^32(约4×10^9)IPv4 头结构 IPv6地址长度:128位地址数量:2^128(约3.4×10^38)IPv6 头结构 IPv6 与 IPv4 头部对比 IPv4 与 IPv6 的比较描述IPv4IPv6IP头部长度为 32 位(4 个...
  • I、Q 通道幅相不平衡的影响及改善

    千次阅读 2017-04-08 11:51:09
    【 摘要】 分析了接收机 I、Q 通道幅相不平衡产生的镜像信号对后续信号处理的影响及可取的误差校正技术。介绍了抑制镜像信号的 D PD 技术。   1 引言 现代雷达为了获得高性能, 均采用先进的信号处理技术, 对需要...
  • 不可变类只是其实例不能修改的类。每个实例中包含的所有信息都必须在...存在不可变的类有有许多理由:(对于可变的类) 1.容易设计,实现和使用, 2.不容出错,且更加安全。实现不可变类需要遵守以下规则:1.不要
  • PS中色饱合度/选颜色/色彩平衡/曲线的区别和运用方法详解 整体思路: 1、使用颜色混合模式营造照片基调。 2、使用色彩平衡对不同曝光区域进行调整,营造色偏。 3、使用选颜色加强灯光的表现力。 ...
  • 电压比较电路

    万次阅读 多人点赞 2019-07-06 15:03:56
    一、电压比较器是对输入信号进行鉴幅与比较的电路,是组成非正弦波发生电路的基本单元电路。电压比较器可以用作模拟电路和数字电路的接口,还可以用作波形产生和变换电路等。由于比较器的输出只有低电平和高电平两种...
  • JSON与XML的区别比较

    万次阅读 多人点赞 2019-06-20 09:19:52
     XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的编码明显比XML容易许多,即使借助工具也能写出JSON的代码,可是要写好XML就太容易了。 (4).解码难度方面。  XML的...
  • 滤波器

    万次阅读 2016-12-12 13:00:15
    采用多滤波结构,利用多个阶数较低的滤波来实现原本阶数较高的滤波,而且每个分支滤波器处理的数据速率仅为原数据速率的I/D,这为工程上高速率实时信号处理提供了实现途径   多滤波结构 信道化...
  • Randao 证公平随机数(VRF)白皮书

    万次阅读 2019-03-26 09:38:19
    Randao 继承了常用随机数发生器的不可控制性及不可预测性,同时具备其所不具有的可参与性及可证公平性。Randao 通过为每个利益相关的个体提供参与的通道,使个体可以观察到自己对随机数生成的...
  • 复数与量法

    千次阅读 多人点赞 2018-09-05 16:49:13
    幅值、角(指数形式): (r是幅值,θ 是角 ) 两种形式相互转换: 【证明】 若 ,则 所以 ,实部 ,虚部 幅值 ,角 极坐标表示法: 一个非零复数z 的辐角有无穷多个值,它们相差 的整数倍,但...
  • Java中字符串的比较

    万次阅读 多人点赞 2018-06-02 09:38:19
    “==”比较两个对象时,比较的是两个对象的内存地址equals() 比较的是... a==b,返回true 而在Java中字符串的值是不可改变的,相同的字符串在内存中只会存一份,所以a和b指向的是同一个对象; (2)String a=ne...
  • 比较器的使用方法的研究

    千次阅读 2018-05-09 20:09:36
    在同相比较电路中,当输入电压超过反相电压时,输出电压将从低电平转换到高电平。在反相比较电路中,当输入电压超过加到同相端参考电压时,输出将从高电平转变为低电平。 可以将比较器当作一个1位模/数转换器(ADC)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 821,617
精华内容 328,646
关键字:

不可相比叫