java基础 包装类、String类、StringBuffer、StringBuilder、Math类、Arrays类

目录

18、包装类(Wrapper)

1、包装类的类型

2、包装类的常用方法

3、Integer创建机制

19、String类

1、继承关系

2、两种创建方式

方式一:直接赋值 String s = “ww”;

方式二:调用构造器创建 String s = new String("ww")

3.常用方法

20、StringBuffer和StringBuilder

1、常用方法

2、String、StringBuilder、StringBuffer的比较

21、Math类

22、Arrays类


18、包装类(Wrapper)

1、包装类的类型

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

有了类的特点,就可以调用类中的方法了

基本数据类型包装类
booleanBoolean
charCharater
byteByte
shortShort
intInteger
longLong
floatFloat
doubleDouble

加粗的包装类的父类都是 Number

  1. jdk5前是手动装箱和拆箱的 装箱(基本类型 -> 包装类型) 反之是拆箱

    (只要是基本数据类型都可以char 和boolean也一样)

  2. jdk5之后(含jdk5)就有了自动装箱和拆箱

  3. 自动装箱底层调用的是 valueOf()方法 比如int --> Integer 就是调用Integer.valueOf(int a);

 

4.自动拆箱底层调用的是 XXXValue()方法 比如 Integer --> int 就是调用new Integer().intValue(Integer i);

 

面试题

Object obj1 = true ? new Integer(1) : new Double(2.0);
System.out.println(obj1);

输出结果?

答案是 1.0 三元运算法是一个整体,会将new Integer() 的结果变成Double精度 所以出来的是1.0而不是1

2、包装类的常用方法

public class WrapperTest {
    public static void main(String[]args){
        //获取最小值
        int minValue = Integer.MIN_VALUE;
        //获取最大值
        int maxValue = Integer.MAX_VALUE;
​
        //判断是不是数字
        boolean a = Character.isDigit('a');
        //判断是不是字母
        boolean b = Character.isLetter('b');
        //判断是不是大写
        boolean a1 = Character.isUpperCase('a');
        //判断是不是小写
        boolean c = Character.isLowerCase('c');
        //判断是不是空格
        boolean whitespace = Character.isWhitespace(' ');
        //转换成大写
        char a2 = Character.toUpperCase('a');
        //转换成小写
        char a3 = Character.toLowerCase('A');
    }
}

3、Integer创建机制

经典面试题

public void method1() {
​
    Integer i  =new Integer(1);
    Integer j  =new Integer(1);
    System.out.println(i == j);  //false
​
    Integer m = 1;
    Integer n = 1;
    System.out.println(m == n);  //true
​
    Integer x = 128;
    Integer y = 128;
    System.out.println(x == y);  //false
​
}

== 引用数据类型比较的是地址是否相同

第一个 只要new就是创建一个新的对象 因此返回false

第二个 这个就涉及Integer 自动装箱的底层原理, 我们知道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);
}

因此这个是关键

 if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];

通过源码可以看到

 static final int low = -128;
  static final int high; 
  static {
   h = 127
  }
 
 /*
 所以知道数字在-128 到127之间的数都是从 数组中取  
 因此如何符合这个范围 取到的都是同一个对象
 因此 第二个 得到true  
 第三个128 不在这个范围  得到的是false
 */

习题二

Integer i = 127;
int j =127;
System.out.println(i == j)
//这里如果有基本数据类型,判断的是值是否相同
所以是true

19、String类

字符串字符使用Unicode字符编码,一个字符不管是字母还是汉字都是占两个字节

1、继承关系

 

  • String 是一个final修饰的类 代表String不能被继承

  • String的存储是通过 字符数组存储的,真正存储字符串内容的是通过这个数组

/** The value is used for character storage.
     该值用于字符存储。
*/
private final char value[];
  • 注意这个 value是一个final类型 不可修改 --》是地址不可以修改 但是可以修改字符数组中内容的(但是这个字符数组还是private的,并且没有提供外部访问方法,因此只要字符串值改变了就是地址就发生了改变)

2、两种创建方式

方式一:直接赋值 String s = “ww”;

先从常量池查看是否有"ww"数据空间,如果有,直接指向;如果没有则重写创建,然后指向。S最终指向的是常量池中的空间地址

方式二:调用构造器创建 String s = new String("ww")

先在堆中创建空间,里面维护了value属性,指向常量池"ww"的空间。如果常量池没有,重新后仓健,如果有直接通过value指向。最终指向的是堆中空间地址

内存分析图

 

面试题

String a = "hello" + "world" ;

创建了几个对象?

只是创建了一个对象 helloworld

编译器不是傻子,这里做了优化,判断创建的常量池对象,是否有引用

(正常我们思路是创建三个 hello 、world、helloworld,但是hello和world没有引用,因此不创建 只创建一个helloworld)

面试题2

String a ="hello"

String b = "abc"

String c =a + b

创建了几个对象?并画出内存图

我认为创建了6个对象(不要纠结创建了几个对象,重点看内存分析)

常量池中 hello abc helloabc 三个对象

堆中创建了StringBuilder 、 创建了一个新的String赋值给了c 、然后StringBuilder还创建了char[]数组对象

 

证明代码:

public class WrapperTest {
    public static void main(String[]args){
        String a ="hello";
        String b = "abc";
        String c =a + b;
        String d = "helloabc";
        String e = "hello" + "abc";
        System.out.println(c == d);  //false
        System.out.println(d == e);//true
​
    }
 }

小结

String c1 =“ab” + "cd" 就是常量池相加

String a + b 就是引用相加,是在堆中的

3.常用方法

  • equals 区分大小写,判断内容是否相等

  • equalsIgnoreCase 忽略大小写的判断内容是否相等

  • length 获取字符的个数, 即字符串长度

  • indexOf 获取字符在字符或者字符串在 字符串中第一次出现的索引,如果没有返回-1

  • lastIndexOf 获取字符或者字符串 在字符串中最后出现的索引 如果没有返回-1

  • substring 截取指定范围的子串

  • trim 去除前后空格

  • charAt 获取某索引出的字符,注意不能使用Str[index] 这个方式。

  • toUpperCase 转换为大写字母

  • toLowerCase 转换为小写字母

  • concat 连接字符串

  • replace 替换字符串中的字符

  • split 分割字符串,对应某些分割字符, 转换为字符串数组

  • compareTo 比较两个字符串大小

    • 一个字符一个字符的进行比较,(c大于a 按照Asall码比较)

    • 如果比较出来就返回 相减的值

    • 如果长度和字符都一样则返回0

    • 如果长度不相同,但是有的字符串都相同,返回长度差

  • toCharArray 转换为字符数组

  • format 格式化字符串 %s 字符串 %d整型 %.2f浮点型 %c字符

20、StringBuffer和StringBuilder

java.lang.StringBuffer代表可变的字符序列,可以对字符串内容进行增删

很多方法与String相同,但是StringBuffer是可变长度的,StringBuffer也是一个容器

  • StringBuffer的直接父类是AbstractStringBuffer

  • StringBuffer实现了 Serializable,即StringBuffer对象可以串行化(序列化)进行网络传输

  • 在父类 AbstractStringBuffer 有属性char[] value,不是final类型

  • 该value数组存放我们字符串内容,因此存放在堆中 ,不在是常量池了

  • StringBuffer也是一个final类,不能被继承

  • 因为StringBuffer里面的值可以改变,每次StringBuffer更新内容,不用每次更新地址,效率相较于String是比较高的

String str = null;
​
StringBuffer sb = new StringBuffer();
​
sb.append(str);  //如果为null其实底层调用的是AbstractStringBuilder的appendNull()方法 将null加入进去 
​
System.out.println(sb.length())  ;  //因此输出的4  
​
System.out.println(sb) ; //其实调用的toString方法  输出的是null字符串
​
StringBuffer sb1 = new StringBuffer(str); //这里底层调用的是 Super(str.length()+16);  
//因此会出现异常  NullpointerException 空指针异常

StringBuilder与StringBuffer是类似的 ,只不过是StringBuilder是线程不安全的,效率更加高效

1、常用方法

  • 增 append()

  • 删 delete(start,end)

  • 替换 replace(start,end,str)

  • 查 indexOf(str) 查找字符串第一次出现的索引,如果没有返回-1

  • 插入 insert()

  • 获取长度 length()

2、String、StringBuilder、StringBuffer的比较

  1. StringBuffer和StringBuilder非常相似,均代表可变的字符序列,而且方法是也一样

  2. String:不可变字符序列,效率低,但是复用性高(常量池可以被多次使用)

  3. StringBuffer可变字符序列,效率很高 是线程安全的

  4. StringBuilder 可变字符序列 ,效率更高 ,是线程不安全的

如果频繁的修改String ,不建议使用String

使用结论

  1. 如果字符串存在大量的修改操作,一般使用StringBuffer或者StringBuilder

  2. 如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder

  3. 如果字符串存在大量的修改操作,并在多线程的情况,使用StringBuffer

  4. 如果字符串很少修改,被多个对象引用,使用String ,比如配置信息等

21、Math类

常用方法 都是静态方法 使用类名. 调用即可

  1. abs绝对值

  2. pow求幂(几次方)

  3. ceil先上取整

  4. floor向下取整

  5. round四舍五入

  6. sqrt求开方

  7. random求随机数([0,1]的随机数)

  8. max 求两个数的最大值

  9. min求两个数的最小值

22、Arrays类

Arrays类里面包含了一系列的静态方法,用于管理或操作数组(比如排序和搜索)

  1. toString返回数组的字符串形式 Arrays.toString(arr)

    public static void main(String[]args){
        int[] arr = {1, 20, 90};
        System.out.println(Arrays.toString(arr)); //[1, 20, 90]
    }

  2. sort 排序 (自然排序和定制排序)

    自然排序

    public static void main(String[]args){
        int[] arr = {1, -3, 4, 145, 90};
        System.out.println(Arrays.toString(arr));//[1, -3, 4, 145, 90]
        //排序
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));//[-3, 1, 4, 90, 145]
    }

    定制排序

    public static void main(String[]args){
        Integer[] arr = {1, -3, 4, 145, 90};
        System.out.println(Arrays.toString(arr));//[1, -3, 4, 145, 90]
       
       //排序定制排序  传入两个参数 第一个参数是要排序的数组  第二个参数是比较器
        //实现了Comparator接口的匿名内部类,要求实现compare接口
        //o1 - o2 是升序排序   o2 - o1 是降序排序
        Arrays.sort(arr, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        //lambda表达式可以写成
        /* 
            Arrays.sort(arr, (o1,o2) -> o1 - o2);
        */
        System.out.println(Arrays.toString(arr));//[-3, 1, 4, 90, 145]
    }

  3. binarySearch通过二分搜索法进行查找,要求必须排好序 Arrays.binarySearch(arr, target)

    public static void main(String[]args){
    
        Integer[] arr = {1, -3, 4, 145, 90};
        Arrays.sort(arr);
        //使用二分搜索查找 必须是排好序的
        //如果找到就返回索引  
        System.out.println(Arrays.binarySearch(arr, 4)); //2
        //如果没有找到就返回  -(low + 1)  low是应该存在的位置 
        //{-3,1,4,90,145}
        //22 在4 和 90 之间  如果存在就是在 4的索引的后一位 即3
        System.out.println(Arrays.binarySearch(arr, 22)); //-4
        //-4  在-3 之后  如果存在 low等于0 
        System.out.println(Arrays.binarySearch(arr, -4));//-1
    }

  4. copyOf 数组元素复制

      public static void main(String[]args){
            Integer[] arr = {1, -3, 4, 145, 90};
            //从arr数组 拷贝arr.length到新数组中
            Integer[] integers = Arrays.copyOf(arr, arr.length);//[1, -3, 4, 145, 90]
            Integer[] integers2 = Arrays.copyOf(arr, 2); //[1, -3]
            Integer[] integers3 = Arrays.copyOf(arr, arr.length+1); //[1, -3, 4, 145, 90, null]
            System.out.println(Arrays.toString(integers));
            System.out.println(Arrays.toString(integers2));
            System.out.println(Arrays.toString(integers3));
        }
    ​
    注入如果是第二个参数是负数  就会抛出异常 
      这个方法底层实际上使用的是System.arraycopy()

  5. file 数组元素的填充

     public static void main(String[]args){
            Integer[] arr = {1, -3, 4, 145, 90};
            //从arr数组 拷贝arr.length到新数组中
            Arrays.fill(arr,99);
            System.out.println(Arrays.toString(arr)); //[99, 99, 99, 99, 99]
        }

  6. equals 比较两个数组元素内容是否相同

       public static void main(String[]args){
            Integer[] arr = {1, -3, 4, 145, 90};
            Integer[] arr2 = {1, -3, 4, 145, 90};
            //从arr数组 拷贝arr.length到新数组中
           Integer[] arr3= {22,2};
            System.out.println(Arrays.equals(arr, arr2)); //true
            System.out.println(Arrays.equals(arr, arr3)); //false
        }

  7. asList 将数组转换成List

       public static void main(String[]args){
            Integer[] arr = {1, -3, 4, 145, 90};
            List<Integer> integers = Arrays.asList(arr);
        }
    编译类型是 List   其实编译类型是ArrayList

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值