1. 成员变量 和 局部变量 的区别
● 语法形式 :从语法形式上看,成员变量是属于类的,而局部变量是在代码块或方法中定义的变量或是方法的参数;成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。
● 存储方式 :从变量在内存中的存储方式来看,如果成员变量是使用 static 修饰的,那么这个成员变量是属于类的,如果没有使用 static 修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存。
● 生存时间 :从变量在内存中的生存时间上看,成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动生成,随着方法的调用结束而消亡。
● 默认值 :从变量是否有默认值来看,成员变量如果没有被赋初始值,则会自动以类型的默认值而赋值(一种情况例外:被 final 修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值
2 . 静态方法 和 实例方法 区别
1、调用方式
在外部调用静态方法时,可以使用 类名.方法名 的方式,也可以使用 对象.方法名 的方式,而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象 。
不过,需要注意的是一般不建议使用 对象.方法名 的方式来调用静态方法。这种方式非常容易造成混淆,静态方法不属于类的某个对象而是属于这个类。
因此,一般建议使用 类名.方法名 的方式来调用静态方法。
2、访问类成员是否存在限制
静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),不允许访问实例成员(即实例成员变量和实例方法),而实例方法不存在这个限制。
3. 基本数据类型 和 包装类 的区别
● 成员变量包装类型不赋值就是 null ,而基本类型有默认值且不是 null。
● 包装类型可用于泛型,而基本类型不可以。
● 基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中,基本数据类型的成员变量(未被 static 修饰 )存放在 Java 虚拟机的堆中。包装类型属于对象类型,我们知道几乎所有对象实例都存在于堆中。
● 相比于对象类型, 基本数据类型占用的空间非常小。
4. 局部变量一定存储在栈中吗?
一般情况下,局部变量(local variable)是存放在调用栈(call stack)上的,也就是存放在栈帧中。每当有一个新函数调用时,就会为该函数创建一个新的栈帧,该函数内所定义的局部变量就存储在该栈帧中。
但是,某些编译器可能会对没有被使用的局部变量进行优化,将其直接剔除掉,而不将其存入栈中。另外,在某些情况下,编译器也可能会将某些局部变量存放在寄存器中,以提高程序的执行效率。因此,总体来说,虽然大多数情况下局部变量是存放在栈中的,但并不绝对。
5. 包装类型的缓存机制
Java中的包装类型(Wrapper Class)是为了将基本数据类型转换成对象而设计的。每种基本数据类型都有对应的包装类:Integer、Float、Double、Long、Boolean、Byte、Short、Character。
在 Java 1.5 及以后的版本中,Java通过使用缓存机制来提高包装类型的性能。具体操作如下:
对于 byte、short、integer 这三种类型的包装类,会预先创建 -128~127 这些范围内的所有数值的包装类对象,并保存在一个叫做“cache”的数组中。
对于 Boolean 类型,JVM预先创建了 TRUE 和 FALSE 两个对象,并保存在 Boolean.cache 数组中。
对于 Char 类型,Java则保存了从 ‘\u0000’ 到 ‘\u007F’ 字符的包装类对象,因为大部分字符都被使用得很少,没有必要进行全部缓存。
对于 Float、Double 等其他类型的包装类,由于它们的值域比较大,缓存区间也比较大,所以 JVM 没有为其提供默认的缓存实现。
当自动装箱时,如果需要创建的包装类型已经存在于缓存数组中,就直接返回该缓存数组中的对象;否则,再去创建一个新的对象。
这种缓存机制可以避免 Java 中因自动装箱和拆箱过程中频繁创建对象带来的性能损失,提高 Java 程序的执行效率。