byte 8字节
char 16字节
short 16字节
int 32字节
float 32字节
long 64字节
double 64字节
boolean ~未定义,底层转换为int类型中的1和0来表示true和false
每个基本数据类型都有对应的
包装类型,基本数据类型与包装类型之间使用会装箱与拆箱。
int total = 99; //执行Integer.valueOf(99); int totalprim = total; //执行 total.intValue();
Integer total = 99;
执行上面那句代码的时候,系统为我们执行了:
Integer total = Integer.valueOf(99);
int totalprim = total;
执行上面那句代码的时候,系统为我们执行了:
int totalprim = total.intValue();
那么valueOf和intValue有什么区别呢?
//valueOf public static Integer valueOf(int i) { return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128]; } ///intValue public int intValue() { return value; }
valueOf它会首先判断i的大小:如果i小于-128或者大于等于128,就创建一个Integer对象,否则执行SMALL_VALUES[i + 128]。在Integer对象中传入的一个value变量进行初始化,如果传入的是String则会将String’转换为int类型后进行初始化。
而在SMALL_VALUES[i + 128]中它是一个静态的Integer数组对象,也就是说最终valueOf返回的都是一个Integer对象。
所以我们这里可以总结一点:装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗,影响性能。
intValue则是直接返回值。
new:每次都会创建一个新的对象。
valueOf:会先在缓冲池中寻找对象,找到对应对象则直接使用缓冲池对象,多次调用使用的是同一个缓冲池对象的引用。
Integer x = new Integer(1); Integer y = new Integer(1); x == y ? //false Integer x = Integer.valueOf(1); Integer y = Integer.valueOf(1); x == y ? //true
String的声明为final类,无法被继承(基本数据类型的包装类也无法被继承)。
String在java8中使用char存储数据。
原码如下:
public final class String implements Serializable, Comparable<String>, CharSequence { private final char[] value; private int hash; private static final long serialVersionUID = -6849794470754667710L; private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0]; public static final Comparator<String> CASE_INSENSITIVE_ORDER = new String.CaseInsensitiveComparator(); }
在java 9 后改为了使用byte存储数据。
String中的value数组被声明为final也就是不可变,这就意味着String在初始化之后不能引用其他类型数据。同时在String中没有方法能改变value的值,因此就可以保证String的值不可变,那么这么做的好处是什么?
1.可以缓存hash值
2.String pool的需要
当String对象被创建过之后就会从String中取得引用,而只有String不可变才能使用String Poll。
3.安全性
String往往被当做参数传递,String不可变就意味着参数不可变。
4.线程安全
1.可变性
String 不可变
StringBuffer和StringBuilder可变
2.线程安全
String 不可变,因此线程安全
StringBuilder 不是线程安全的。
StringBuffer 是线程安全的,通过synchronized进行同步。
在java中方法的参数传递只有值传递没有引用传递。
class Example{ public static void main(String[] args){ Test t = new Test("a"); change(t) System.out.println(t.name);//b } public static void change(Test t){ t.setName("b"); } }
在上述代码中t 指针存储的是对象的地址,在方法中传递的是对象t的地址,是将对象地址以值的形式进行传递,所以在后续修改对象name的时候由于使用的是同个独享地址所以t对象的name就会被修改为b。
java中无法使用隐式向下转型。因为这会损失一部分精度。
float f = 1.1; //错误
字面量为double,不能直接赋值给float因为这是向下转型。正确写法应该是:
float f = 1.1f;
但是在使用+=或则++的的时候可以执行隐式类型转换。