常用类

包装类

针对八种基本数据类型相应的引用类型就是包装类

基本数据类型 包装类
boolean Boolean
char Character
byte Byte
short Short
int Integer
long Long
float Float
double Double

包装类和基本数据类型的转换

装箱:从基本数据类型转换到包装类
拆箱:从包装类转换到基本数据类型
在JDK5之前只能手动的装箱和拆箱,在JDK5之后,可以自动的装箱和拆箱,底层原理还是一样。装箱可以使用下面的方法:

  • new 包装类(基本数据类型)例如:new Integer(10)
  • Integer.valueOf(基本数据类型)

拆箱调用的是包装类的方法,例如Integer就是intValue();

 //在JDK5之前的手动装箱和拆箱
//装箱
int n1 = 10;
Integer integer = new Integer(n1);
Integer integer1 = Integer.valueOf(n1);

//拆箱
int n2 = integer.intValue();

//在JDK5之后自动装箱拆箱
int n3 = 20;
Integer integer2 = n3;

int n4 = integer2;
Object obj1 = true ? new Integer(1):new Double(2.0);
System.out.println(obj1);//1.0 
//三元运算符是一个整体,会提升优先级

Object obj2 = null;
if(true){
    obj2 = new Integer(1);
}else{
    obj2 = new Double(2.0);
}
System.out.println(obj2);//1

注意:三元运算符是一个整体

包装类型和String类型的转换

包装类到String的方式:

  • 将包装类和空字符串相加 i1 + "";
  • 调用包装类的toString方法
  • 使用String.valueOf(包装类)
Integer i1 = 10;//自动装箱
//包装类到String转换
String str1 = i1 + "";
String str2 = i1.toString();
String str3 = String.valueOf(i1);
//从String到包装类的转换
String str = "123";

Integer i1 = Integer.parseInt(str);
Integer i2 = new Integer(str);

一个经典面试题:

Integer i1 = new Integer(1);
Integer i2 = new Integer(1);
System.out.println(i1 == i2);//false


Integer i3 = 1;
Integer i4 = 1;
System.out.println(i3 == i4);//true

Integer i5 = 128;
Integer i6 = 128;
System.out.println(i5 == i6);//false

第一个为false,使用new创建两个对象,两个对象的地址肯定不一样,所以为false;第二个,设计到自动装箱,自动装箱的调用的是valueOf方法,查看对象源码,可以知道,如果我们装箱的数在-128-127之间,我们返回的是缓存中的对象,所以第二个为true,第三个为false。

String

String类型是用于保存字符串,也就是一组字符序列
字符串的字符编码是使用Unicode编码,一个字符(不管是英文还是汉字)都占二个字节
String类有很多构造器,实现构造器的重载
String实现了Serializable接口,可以串行化,在网络中传输,实现了Comparable接口,可以比较大小
String类是final修饰,不能被其它类继承
String类使用:private final char value[];保存数据,所以是不可修改的,不可修改值的是value不能再重新指向一个新的地址,并不是value里面的内容不能修改,里面的单个字符还是可以修改的

String的创建方式

String有两种创建方式:直接赋值创建或者使用构造器创建

  • 直接赋值,当使用直接赋值的时候,会在常量池中寻找有没有对象的字符串,如果有直接返回地址,没有就创建一个字符串并返回一个地址
  • 构造器创建,当使用构造器创建的时候,会在堆中开辟一个空间,里面有一个value属性,先从常量池中寻找,有没有对象字符串,有将对应字符串地址返回给value,没有就在常量池创建一个字符串并将地址返回给value。

内存图:

String str = "hello" + "abc";
//在内存中创建几个对象?
/*
实际上不会创建三个对象,只会创建一个对象,编译器会在底层进行优化,创建一个对象“helloabc"所以等同于下面的语句
String str = "helloabc";

*/

String a = "hello";
String b = "abc";
String c = a + b;
//在内存中一共创建几个对象?3个
/*
a,b我们可以肯定的知道,他们一定是在常量池中创建了两个对象,分别是“hello”和"abc“,那么就要看String c = a + b;底层是如何执行,我们加断点,查看源码:
1.首先会创建一个StringBuilder对象
2.调用append方法将a添加
3.继续调用append方法将b添加
4.调用toString方法,返回一个new String()对象
所以这里的c指向的是堆中的字符串对象
*/

常量相加我们看的是常量池,变量相加我们看的是堆中

String常用方法

StringBuffer

代表的是可变的字符序列,可以对字符串内容进行增删,很多方法和String相同,但StringBuffer长度是可变的,StringBuffer是一个容器

1.StringBuffer的直接父类是AbstracStringBuilder

2.实现了Serializable接口,可以进行串行化,用于网络传输

3.在父类中有一个属性:char[] value;用于保存数据,不是final

4.StringBuffer是一个final类,不可以被继承

5.相比较于String效率会更高,不用每次都更新地址,直接在value中添加数据

StringBuffer构造器

  1. 使用空构造器创建一个StringBuffer对象,源码分析:

    StringBuffer str = new StringBuffer();
    
    //1.调用父类构造器,并创建一个容量为16的字符数组大小的容器
    public StringBuffer() {
        super(16);
    }
    
  2. 使用指定初始容量的构造器,会创建指定大小容器的:

    StringBuffer str = new StringBuffer(100);
    
    public StringBuffer(int capacity) {
        super(capacity);
    }
    
  3. 使用指定字符串创建,会创建一个字符串长度+16大小的容器

    StringBuffer str = new StringBuffer("hello");
    
    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }
    

String与StringBuffer转换

从String转换到StringBuffer有两种方式:
1.使用StringBuffer构造器

2.先创建一个空的StringBuffer对象,然后使用append添加字符串

String str = "hello";
        
StringBuffer str1 = new StringBuffer(str);
StringBuffer str2 = new StringBuffer();
str2.append(str);

从StringBuffer转换到String,有两种方式:
1.使用toString方法

2.使用String构造器

StringBuffer str = new StringBuffer("hello");
        
String str1 = str.toString();
String str2 = new String(str);

StringBuffer常用方法

StringBuffer stringBuffer = new StringBuffer();
//增
stringBuffer.append("true");
stringBuffer.append(true);
//删
System.out.println(stringBuffer);
stringBuffer.delete(0,1);
System.out.println(stringBuffer);
//改
stringBuffer.replace(0,1,"11");
System.out.println(stringBuffer);
//插入
stringBuffer.insert(1,"hello");
System.out.println(stringBuffer);
//获取长度
System.out.println(stringBuffer.length());
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);
System.out.println(sb.length());//4
System.out.println(sb);//null
//查看底层源码
@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}
//直接调用父类的append方法
public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}
//我们这里传入的null,所以调用appendNull方法返回
private AbstractStringBuilder appendNull() {
    int c = count;
    ensureCapacityInternal(c + 4);
    final char[] value = this.value;
    value[c++] = 'n';
    value[c++] = 'u';
    value[c++] = 'l';
    value[c++] = 'l';
    count = c;
    return this;
}
//所以这里的count等于4,返回长度是4,输出的null

StringBuilder

一个可变的字符序列,提供了与StringBuffer兼容的API,不保证同步,是StringBuffer的一个简易替换,用在字符串缓冲区被单个线程使用的时候,如果可能,简易优先采用这个类。

1.StringBuilder的直接父类是AbstracStringBuilder

2.实现了Serializable接口,可以进行串行化,用于网络传输

3.在父类中有一个属性:char[] value;用于保存数据,不是final

4.StringBuilder是一个final类,不可以被继承

5.相比较于String效率会更高,不用每次都更新地址,直接在value中添加数据

6.所有的方法都不是线程安全的,在单线程中使用

String、StringBuffer、StringBuilder之间的比较

  1. StringBuffer和StringBuilder均代表可变字符序列,二者的方法也是相识的
  2. String代表不可变字符序列,效率低,但复用性高
  3. StringBuffer可变字符序列,效率较高(增删),线程安全
  4. StringBuilder可变字符序列,效率最高(增删),线程不安全
  5. 如果对字符串做大量的修改,不要使用String

使用结论:

  1. 如果字符串存在大量的修改操作,一般使用StringBuffer或者StringBuilder
  2. 如果字符串存在大量的修改操作,在单线程中使用,使用StringBuilder
  3. 如果字符串存在大量的修改操作,在多线程中使用,使用StringBuffer
  4. 如果字符串很少被修改,被多个对象引用,使用String,比如配置信息

System

System作为系统类,在JDK的java.lang包中,可见它也是一种java的核心语言特性。System类的构造器由private修饰,不允许被实例化。因此,类中的方法也都是static修饰的静态方法。

exit():退出程序,exit(int)方法终止当前正在运行的 Java 虚拟机,参数解释为状态码。根据惯例,非 0 的状态码表示异常终止。 而且,该方法永远不会正常返回。 这是唯一一个能够退出程序并不执行finally的情况。

arraycopy():复制数组元素

int[] nums = {1,2,3,4};
int[] num1 = new int[4];

System.arraycopy(nums,0,num1,0,nums.length);
System.out.println(Arrays.toString(num1));
//[1, 2, 3, 4]

currentTimeMillens():获取当前时间的毫秒数

gc():运行垃圾回收机制,调用 gc 方法暗示着 Java 虚拟机做了一些努力来回收未用对象失去了所有引用的对象,以便能够快速地重用这些对象当前占用的内存。当控制权从方法调用中返回时,虚拟机已经尽最大努力从所有丢弃的对象中回收了空间。

BigInteger、BigDecimal

BigInteger适合保存比较大的整数

BigInteger bigInteger = new BigInteger("1234567890000000");
BigInteger bigInteger1 = new BigInteger("100");
BigInteger add = bigInteger.add(bigInteger1);//加
BigInteger subtract = bigInteger.subtract(bigInteger1);//减
BigInteger multiply = bigInteger.multiply(bigInteger1);//乘
BigInteger divide = bigInteger.divide(bigInteger1);//除
System.out.println(bigInteger);
System.out.println(add);
System.out.println(subtract);
System.out.println(multiply);
System.out.println(divide);
/*
1234567890000000
1234567890000100
1234567889999900
123456789000000000
12345678900000
*/

BigDecimal适合保存精度更高的浮点数

BigDecimal bigDecimal = new BigDecimal("123.45678902345");
BigDecimal bigDecimal1 = new BigDecimal("2.0");
System.out.println(bigDecimal.add(bigDecimal1));
System.out.println(bigDecimal.subtract(bigDecimal1));
System.out.println(bigDecimal.multiply(bigDecimal1));
System.out.println(bigDecimal.divide(bigDecimal1));
/*
125.45678902345
121.45678902345
246.913578046900
61.728394511725
*/

日期

日期一代:Date

Date date = new Date();//获取当前时间
Date date1 = new Date(12340000L);//获取指定毫秒数的日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");//指定日期的格式
String time = sdf.format(date);//将日期按指定格式输出为字符串
System.out.println(sdf.format(date1));
System.out.println(time);
//将字符串转换成日期
String strTime = "2020年1月1日 17:23:23";
Date date2 = sdf.parse(strTime);
System.out.println(sdf.format(date2));

日期二代:Calendar日历类

Calendar c = Calendar.getInstance();//获取当前日历类
System.out.println(c);
System.out.println("年:" + c.get(Calendar.YEAR));
System.out.println("月:" + (c.get(Calendar.MONTH)+1));
System.out.println("日:" + c.get(Calendar.DAY_OF_MONTH));
System.out.println("时:" + c.get(Calendar.HOUR));
System.out.println("分:" + c.get(Calendar.MINUTE));
System.out.println("秒:" + c.get(Calendar.SECOND));

注意获取月份的时候,要加1,月份是从零开始计算

日期三代:LocalDate(日期)、localTime(时间)、LocalDateTime(日期时间),这些都在JDK8中引入

//常规使用
LocalDateTime ldt = LocalDateTime.now();//获取当前日期时间
//获取年月日,时分秒
System.out.println("年:" + ldt.getYear());
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 sdf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
System.out.println(sdf.format(ldt));

//时间戳Instant
Instant instant = Instant.now();
System.out.println(instant);
//Instant->Date
Date date = Date.from(instant);
//Date -> Instant
Instant instant1 = date.toInstant();
posted @ 2021-10-03 16:20  无涯子wyz  阅读(64)  评论(0)    收藏  举报