包装类值基本数据类型对应的引用类型,包装类封装好的方法能够很方便的让我们操作基本数据类型而不需要自己再去编写不必要的代码。
基本数据类型 | 包装类 |
---|---|
boolean | Boolean |
char | Char |
byte | Byte |
short | Short |
int | Integer |
long | Long |
floast | Float |
double | Double |
首先,引出装箱和拆箱两个概念,装箱:基本数据类型->引用类型,拆箱:引用类型->基本数据类型。
jdk5以前需要手动装箱和拆箱,比较麻烦。jdk5以后自动进行装箱和拆箱。
int n = 100; //自动装箱 int->Integer Integer integer = n; //底层使用的是 Integer.valueOf(n2) //自动拆箱 Integer->int int n2 = integer; //底层仍然使用的是 intValue()方法
以Integer类型和String类型为例
//包装类(Integer)->String Integer i = 100;//自动装箱 //方式 1 String str1 = i + ""; //方式 2 String str2 = i.toString(); //方式 3 String str3 = String.valueOf(i); //String -> 包装类(Integer) String str4 = "12345"; Integer i2 = Integer.parseInt(str4);//使用到自动装箱
先来看一道面试题
public static void main(String[] args) { Integer i = new Integer(1); Integer j = new Integer(1); System.out.println(i == j);//False Integer m = 1; //底层 Integer.valueOf(1); Integer n = 1;//底层 Integer.valueOf(1); System.out.println(m == n); //True Integer x = 128;//底层 Integer.valueOf(128); Integer y = 128;//底层 Integer.valueOf(128); System.out.println(x == y);//False }
这里输出False,True,False。
首先第一个好理解,使用new操作符,两个Integer类变量指向不同的对象,当然是不相等的。
第二个和第三个需要理解底层机制,因为这里自动装箱,底层调用的是valueof() 方法,源码如下:
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
分析一下可以知道当 i 在 IntegerCache.low(-128)~IntegerCache.high(127)范围内,Integer对象就直接从数组返回,这个数组是在类加载时就已经初始化好了,如果超出了这个范围,则会重新new一个Integer对象。
String s1 = "yjh"; String s2 = new String("yjh");
以上两种创建方式存在区别
方式一:先在常量池中查找是否有存储"yjh"的空间,如果有则直接返回常量池的地址,如果没有,则在常量池创建"yjh"并返回地址,即s1最终指向的是常量池的地址。
方式二:先在堆中创建对象,里面的value属性指向字符串常量"yjh",如果没有则创建并返回地址给value,s2最终指向的是堆中的空间地址。
下面的例子帮助理解String对象的创建
测试题一:
String a = "abc"; String b = "abc"; System.out.println(a.equals(b))//true System.out.println(a == b)//true
测试题二:
String a = "yjh"; String b = new String("yjh"); System.out.println(a == b)//false System.out.println(a == b.intern())//true System.out.println(b == b.intern())//false
说明:intern()方法返回String对象的字符串在常量池中的地址
String是不可变类,字符串对象一旦被分配,内容是不可变类。所以在每次给String变量赋值时,都会重新返回一个新的对象给String变量。
//以下语句创建了几个对象 String s = "hellp"; s = "world
解析:创建了两个对象,前后两个s指向的不是同一个对象。
//创建了几个对象 String s = "hello" + "world";
解析:创建了一个对象,编译器做一个优化:s = "hello" + "world" -> s = "helloworld"
//a,b,c三个对象内存分布,分析第三句代码底层执行过程 String a = "hello"; String b = "world"; String c = a + b;
由于String不可变,每次更新或者拼接新的字符串都会新创建一个对象,当有大量的修改操作时,效率很低。因此Java提供了StringBuffer和StringBuilder类,字符串长度和内容可以变化。
//String——>StringBuffer String str = "hello tom"; //方式 1 使用构造器 StringBuffer stringBuffer = new StringBuffer(str); //方式 2 使用的是 append 方法 stringBuffer = stringBuffer.append(str); // StringBuffer ->String //方式一:使用toString方法 String s = stringBuffer.toString(); //方式二:使用构造器 String s1 = new String(stringBuffer3);
StringBuilder是StringBuffer的一个简易替换,但不是线程安全的,但是StringBuilder的速度更快,因此在单线程时更多考虑使用StringBuilder。
Java的Random类提供了丰富的随机数生成方法
方法 | 说明 |
---|---|
nextBoolean() | 生成true或者false,两者概率相等 |
nextDouble | 生成[0,1.0)区间的小数 |
nextInt() | 生成int范围的整数 |
nextInt(int n) | 生成[0,n)之间的整数,不包括n |
//生成[a,b)区间的整数 Random r = new Random(); int n = r.nextInt(b-a) + a;
Java先后有三代日历类库,现在的第三代是**LocalDate(日期/年月日),LocalTime(时间/时分秒),LocalDateTime(时间日期/年月日时分秒)
LocalDateTime ldt = LocalDateTime.now() System.out.println("年=" + ldt.getYear()); System.out.println("月 =" + ldt.getMonth());//英文描述 System.out.println("月 =" + ldt.getMonthValue());//数字描述 System.out.println("日=" + ldt.getDayOfMonth()); System.out.println("时=" + ldt.getHour()); System.out.println("分=" + ldt.getMinute()); System.out.println("秒=" + ldt.getSecond());
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");//指定输出格式 String format = dtf.format(ldt);//传入需要格式化的LocalDateTime对象,并返回给String对象 System.out.println("格式化的日期=" + format);
//100天后,日期信息 LocalDateTime localDateTime = ldt.plusDays(890); System.out.println("100 天后=" + dateTimeFormatter.format(localDateTime)); //999分钟后时间信息 LocalDateTime localDateTime2 = ldt.minusMinutes(3456); System.out.println("3456 分钟前 日期=" + dateTimeFormatter.format(localDateTime2))
如果我们要处理的数据超过了long支持的范围或者说我们要求更高的精度,我们可以使用BigInteger类和BigDecimal类。
数学运算 | 方法 |
---|---|
加 | add() |
减 | subtract() |
乘 | mutiply() |
除 | divide() |
学习总结来源于韩顺平老师循序渐进学Java