可以是byte,short,int,char.以及他们的包装类,在JDK1.7之后可以使String.
因为switch只支持int类型数据,但是byte,short,chart,支持隐式转换成int。String是因为JDK1.7之后采用string.hashCode转成int型判断。
基本数据类型中,布尔类型boolean占有一个字节,由于其本身所代码的特殊含义,boolean类型与其他基本类型不能进行类型的转换(既不能进行自动类型的提升,也不能强制类型转换), 否则,将编译出错。
Integer a=null;
switch (a){
case 0:
System.out.println("123");
}
不可以,因为switch只支持int类型,在如上情况中会抛出空指针异常的情况
原因:
混乱使用对象和原始数据值,一个具体的例子就是当我们在一个原始数据值与一个对象进行比较时,如果这个对象没有进行初始化或者为Null,在自动拆箱过程中obj.xxxValue,会抛出NullPointerException,如下面的代码
1.自动类型转换,隐式转换。范围小的存储类型转到存储范围大的类型。
byte->short->int->double->long->float;
char->int->double->long->float;
以上为实验得出赋值不出错。
在char初始化时范围在0-65535。但是不可以用赋值为byte,short,int类型
2.强制类型转换,必须书写代码才能完成的类型转换。
注意问题:强制类型转换通常都会存储精度的损失,所以使用时需要谨慎。
使用包装类中的属性 SIZE,MIN_VALUE,MAX_VALUE.
因为long是整形,double是浮点型,long转double过程中会发生,精度丢失。因为double浮点型数据范围更大。所以long可以转float.
在数值后加L
一个为基础数据类型,一个为包装类。一个初始化为0,一个初始化为null。
Integer涉及到拆箱和自动装箱。范围为-128-127
自动装箱和拆箱:
自动装箱和拆箱从Java 1.5开始引入,目的是将原始类型值转自动地转换成对应的对象。自动装箱与拆箱的机制可以让我们在Java的变量赋值或者是方法调用等情况下使用原始类型或者对象类型更加简单直接。
1.自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,
2.反之将Integer对象转换成int类型值,这个过程叫做拆箱。
3.自动装箱时编译器调用valueOf将原始类型值转换成对象,
4.同时自动拆箱时,编译器通过调用类似intValue(),doubleValue()这类的方法将对象转换成原始类型值。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
装箱范围 Byte,Short,Interger,Long范围为-128-127。Char 0-127。Float和Double不存在装箱,直接创建
public Boolean(boolean value) {
this.value = value;
}
自动装箱的弊端:
自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。
Integer sum = 0;
for(int i=1000; i<5000; i++){
sum+=i;
}
自动拆箱和装箱在对象比较时:
这是一个比较容易出错的地方,”==“可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,这个比较过程中没有自动装箱发生。进行对象值比较不应该使用”==“,而应该使用对象对应的equals方法。看一个能说明问题的例子。
public class AutoboxingTest {
public static void main(String args[]) {
// Example 1: == comparison pure primitive – no autoboxing
int i1 = 1;
int i2 = 1;
System.out.println("i1==i2 : " + (i1 == i2)); // true
// Example 2: equality operator mixing object and primitive
Integer num1 = 1; // autoboxing
int num2 = 1;
System.out.println("num1 == num2 : " + (num1 == num2)); // true
// Example 3: special case - arises due to autoboxing in Java
Integer obj1 = 1; // autoboxing will call Integer.valueOf()
Integer obj2 = 1; // same call to Integer.valueOf() will return same
// cached Object
System.out.println("obj1 == obj2 : " + (obj1 == obj2)); // true
// Example 4: equality operator - pure object comparison
Integer one = new Integer(1); // no autoboxing
Integer anotherOne = new Integer(1);
System.out.println("one == anotherOne : " + (one == anotherOne)); // false
}
}
Output:
i1==i2 : true
num1 == num2 : true
obj1 == obj2 : true
one == anotherOne : false
值得注意的是第三个小例子,这是一种极端情况。obj1和obj2的初始化都发生了自动装箱操作。但是处于节省内存的考虑,JVM会缓存-128到127的Integer对象。因为obj1和obj2实际上是同一个对象。所以使用”==“比较返回true。
在C中不可以,因为C中char一个字节。JAVA中可以,因为Java中char类型占2个字节,而且Java默认采用Unicode编码,以个Unicode码是16位,所以一个Unicode码占两个字节,所以可以。但是有些偏僻字占用更多字节,有些可以,有些不行。
s1=s1+1会编译异常,数据类型不匹配,int类型不能与short相加,小的的不能加小的。
编译不会出错,但是可能会精度丢失; s+=1 <=> s = (s的类型)(s+1)
初始化提示类型不匹配,c的范围是0-65535。
提示,数据类型不匹配,int类型不能与char相加,小的的不能加小的。
编译通过可能精度丢失,c+=1<==>(char)(c+1)
答:2-4个字节,GBK两个,UTF-16 通常两个,BCD扩展4个 UTF-8 通常3个,B区扩展4个。
答:char运算时将字符转化成ASCII码进行整形运算,最后返回值为整形
答:ASCII定义了128个字符的编码,Unicode(联合)包含了所有字符(语言)的编码,只规定了二进制编码,却未规定二进制编码如何存储。UTF-8是Unicode的实现方式之一,GBK和Unicode一样规定了字符的编码,GBK是大陆通用编码。
/**
答:==在基础数据类型中比较其大小,引用类型比较内存地址。
Equals在不重写的情况下与==相同,重写后是按照其本身方法内部规则进行判断。
任何类都继承自Object,Object中有Equals方法,其底层代码:
*/
public boolean equals(Object obj) {
return (this == obj);
}
/**
答:因为String底层是char数组,并且用final修饰。
因此每次创建String其原本字符串并不会消失或被替换,而会新建一个String,存储在字符串常量池中,堆区中
因此在字符串中不要使用+=拼接字符串,在进行字符串拼接,必须使用StringBuilder或StringBuffer
StringBuffer是线程安全的,因为其修改方法用synchronized修饰
*/
private final char value[];
答:基础数据类型是传值,引用类型是传址,地址中的对象还是原对象,栈帧结束后 传值不改变,传址改变;
注意String例外,下面来讲。
public void add(String str){
str+=123;
}
@Test
public void a(){
String str="123";
add(str);
System.out.println(str);
}
//结果是 123 因为对象值并没有变
答案:两个,一个是字符串字面量”xyz”所对应的、驻留(intern)在一个全局共享的字符串常量池中的实例,另一个是通过new String(String)创建并初始化的、内容与”xyz”相同的实例
字符串有两个特性:字符串常量的暂存池特性和不可变性
字符串常量的暂存池:对于相同的字符串常量,每次使用时并不会重新创建一个内存来储存,而是在第一次创建的时候将字符串作为键,将字符串的地址作为值,下次用的时候先去键值对中查找,如果有则直接返回上次创建字符串的地址。这个特性依赖于字符串的不可变性
不可变性:每次字符串发生变化,都会创建一个新的内存。所以,当多个字符串进行拼接的时候,造成了内存的浪费和时间的消耗(因为每次创建对象都要消耗时间,创建对象也是有成本的),所以当大量字符串拼接的时候,应该使用StringBuilder。
StringBuilder在大量字符串拼接的时候,不会重复创建对象,所以也不会产生垃圾内存。
栈变量使用完之后,就会自动释放内存。
而堆里面的内存资源,一般会在程序结束之后才会进行垃圾回收。
他们之间没有继承关系。String是final不可继承。他们底层都是数组 实现Implements-CharSequence接口