Java基础笔记(九)【常用类】

object类

是所有Java类的根基,意味着所有的Java对象都拥有object类的属性和方法。如果在类的声明中未使用extends关键字指明其父类,则默认继承的是object类。

查看某个类的所有方法:按快捷键(ctrl+F12)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2PqWs9m5-1689078910343)(Java笔记.assets/image-20230613132332004.png)]

注意:可以看到方法前的图案有的是锁、有的是解锁、有的是钥匙,说明不同的方法有不同的修饰符(如publicprotectedprivate等)。

该部分仅介绍一下三个方法,其他在线程、反射等再介绍。

equals和==
  • equals():

    • 基本类型比较用==,引用类型比较用equals()

      • ==:基本类型比较的是值,引用类型比较的是地址值。
      • equals:比较的是引用类的地址值。String将Object中的equals方法重写了,比较的就是属性值。
    • 代码分析:

      public class Demo01 extends Object {
          public static void main(String[] args) {
              int a = 10;
              int b = 10;
              System.out.println(a==b);//true
      
              String str = "abc";
              String str2 = "abc";
              System.out.println(str == str2);//true
              System.out.println(str.equals(str2));//true
      
              String str23 = new String("abc");
              String str22 = new String("abc");
              System.out.println(str23 == str22);//false
              System.out.println(str23.equals(str22));//true
          }
      }
      

在这里插入图片描述

对比下ObjectString中的equals方法:
在这里插入图片描述

  • 代码分析:

    //Student类
    public class Student {
        private int age;
        private String name;
    
        public Student() {
        }
    
        public Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
    }
    
    //主方法
    public class Application {
        public static void main(String[] args) {
            Student zs = new Student(10, "zs");
            Student zs1 = new Student(10, "zs");
            System.out.println(zs == zs1);
            System.out.println(zs.equals(zs1));
        }
    }
    
    false
    false
    

    这里Student类没有重写equals方法,所以默认比较的依旧是地址值。

    alt+insert快捷键(一直点next,不用自己写)重写下equals方法,再进行比较。得到:

    //Student类
    public class Student {
        private int age;
        private String name;
    
        public Student() {
        }
    
        public Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
    
        //重写equals方法
        @Override
        public boolean equals(Object o) {
            if (this == o) 
                //内存地址相同,值一定相同
                return true;
            if (o == null || getClass() != o.getClass()) 
                return false;
            Student student = (Student) o;
            return age == student.age &&
                    Objects.equals(name, student.name);
        }
    
    }
    
    false
    true
    
  • hashCode():该方法可以理解为返回对象的哈希码值。用于区分不同对象。hash码是一种无序、不重复的一串十六进制数据。可以通过重写的方式自定义hash码的声明规则,让其和属性值相关联,一般在重写equals方法时,都会重写hashCode方法。

    • 哈希表原理:数组下表取值快,内容取值需要一个个从头到尾比较,很慢。哈希表使得内容取值更快,不能存重复数据,即两个值如果相同,存入的hash码也要相同。

      在这里插入图片描述

      比如,我要找某个元素”a“,只需要找对应的哈希码就行了,更快。

    • 代码分析:

      java规定,如果两个值相同,那么hash码也要相同。

      public class Demo02 {
          public static void main(String[] args) {
              String s1 = "kkv";
              String s2 = "kkv";
              System.out.println(s1 == s2);
              System.out.println(s1.equals(s2));
              System.out.println(s1.hashCode());
              System.out.println(s2.hashCode());
          }
      }
      
      true
      true
      106262
      106262
      
    • 注意native关键字:表示java调用非java接口。如c/c++实现。在源码中只有声明,没有实现。

      如:Object中的hashCode()方法。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nd2ULe6V-1689078910348)(Java笔记.assets/image-20230613152132604.png)]

      自定义类同样也要重写hashCode()方法

      public class Student {
          private int age;
          private String name;
      
          public Student() {
          }
      
          public Student(int age, String name) {
              this.age = age;
              this.name = name;
          }
      
          @Override
          public boolean equals(Object o) {
              if (this == o)
                  return true;
              if (o == null || getClass() != o.getClass())
                  return false;
              Student student = (Student) o;
              return age == student.age &&
                      Objects.equals(name, student.name);
          }
      
          @Override
          public int hashCode() {
              return Objects.hash(age, name);
          }
      }
      
      //主方法
      public class Application {
          public static void main(String[] args) {
              Student zs = new Student(10, "zs");
              Student zs1 = new Student(10, "zs");
              System.out.println(zs == zs1);
              System.out.println(zs.equals(zs1));
              System.out.println(zs.hashCode());
              System.out.println(zs1.hashCode());
          }
      }
      
      false
      true
      5168
      5168
      

    总结:自定义的类都需要将hashCode()equals()方法的重写加上。

  • toString():

    同样也需要重写。自动生成后,也可以根据自己的喜好进行修改。

    • 重写前:

      public class Demo03 {
          public static void main(String[] args) {
              Student zs = new Student(11, "zs");
              System.out.println(zs.toString());
          }
      }
      
      //输出
      com.systemcla.object.Student@144f
      
    • 重写后:

      public class Student {
          private int age;
          private String name;
      
          public Student() {
          }
      
          public Student(int age, String name) {
              this.age = age;
              this.name = name;
          }
      
          @Override
          public boolean equals(Object o) {
              if (this == o)
                  return true;
              if (o == null || getClass() != o.getClass())
                  return false;
              Student student = (Student) o;
              return age == student.age &&
                      Objects.equals(name, student.name);
          }
      
          @Override
          public int hashCode() {
              return Objects.hash(age, name);
          }
      
          @Override
          public String toString() {
              return "Student{" +
                      "age=" + age +
                      ", name='" + name + '\'' +
                      '}';
          }
      }
      
      //输出
      Student{age=11, name='zs'}
      

    总结:自定义一个类的时候,将一下方法都写上。实在想省略,不需要比较对象的话可以不写equals()hashCode(),但是toString()要写。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ycah3pCG-1689078910348)(Java笔记.assets/image-20230613153856768.png)]

包装类

  1. 概念:

    针对八种基本类型提供的包装类。后期学习的集合不能存基本类型。在实际应用中经常血药将基本来信转化为对象,便于操作。因此八个和基本类型对应的类型统称为包装类。均位于java.lang包。

基本数据类型包装类
byteByte
booleanBoolean
shortShort
charCharacter
intInteger
longLong
floatFloat
doubleDouble
  • 八个类名中,除了IntegerCharacter类之外,其他六个类的类名和基本类型一致,知识首字母大写。

  • 八个类中,除了CharacterBoolean以外,其他的都是“数字型”,都是java.lang.Number的子类。

  1. 常用方法

    public class Demo01 {
        public static void main(String[] args) {
            //包装类中的常用属性
            System.out.println(Integer.MAX_VALUE);
            System.out.println(Integer.MIN_VALUE);
            System.out.println(Integer.TYPE);
            //1. 把String类型转为int类型(符合范围,格式也对的才能转)
            String str = "123";
            int num = Integer.parseInt(str);
            //2. 把String类型转为Integer类型
            Integer integer = Integer.valueOf(str);
            //3. 把Integer类型转为String类型
            String s = integer.toString();
            String s = integer.toString();
            System.out.println(num);
            System.out.println(integer);
            System.out.println(s);
        }
    }
    
    //输出
    2147483647
    -2147483648
    int
    123
    123
    123
    
  2. 自动装箱,拆箱

    • 手动装箱:把基本类型数据变成对应的包装类 。
    • 手动拆箱:把包装类转成对应的基本数据类型。
    public class Demo02 {
        public static void main(String[] args) {
            System.out.println("------------------手动装箱、拆箱-------------------");
            int a = 10;
            Integer integer = new Integer(a);//手动装箱
            int i = integer.intValue();//手动拆箱
    
            System.out.println("------------------自动装箱、拆箱-------------------");
            //jdk 1.5之后不再使用手动,而是自动
            Integer integer2 = a;//自动装箱,底层还是new Integer()对象
            int j = integer2;//自动拆箱,底层还是intValue()方法
    
            System.out.println("------------------隐藏的装箱、拆箱-----------------");
            Integer c = new Integer(1);
            c++;//隐藏的拆箱,包装类不能自增,这里隐藏的转化成了基本类型
            int cc = 10;
            c.equals(cc);//隐藏的装箱,cc变成包装类
    
        }
    }
    
  3. 常见面试题

    public class InterviewTest {
        public static void main(String[] args) {
            int a = 10;
            Integer b = 10;
            System.out.println(a == b);//true 自动拆箱,b拆箱成基本类型
            System.out.println(b.equals(a));//true 自动装箱,a装箱成引用类型(比较值)
    
            Integer a2 = new Integer(10);
            Integer b2 = new Integer(10);
            System.out.println(a2 == b2);//false
            System.out.println(a2.equals(b2));//true 比较值
    
            Integer a3 = 10;
            Integer b3 = 10;
            System.out.println(a3 == b3);//true 没new,拿到的10的缓存地址值一样
            System.out.println(a3.equals(b3));//true
    
            Integer a4 = 200;//new Integer()
            Integer b4 = 200;//new Integer()
            System.out.println(a4 == b4);//false 有new
            System.out.println(a4.equals(b4));//true
        }
    }
    
    //输出
    true
    true
    false
    true
    true
    true
    false
    true
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pULAWotY-1689078910349)(Java笔记.assets/image-20230614161054919.png)]

    进源码可知,int类型的值在-128~127,不用new;超出范围需要new。

    注意:所有的整数类型对应的封装类才有缓存区。

String类

jdk1.8中,String底层是一个char数组。

9以后,底层变为byte数组。

原因:char类型数据占用2个字节,byte类型仅1个字节,改变后更节省空间。以前的底层value中需要保存字符,9以后保存的是ASCII码。9中的底层coder中检测的是有没有中文,没有置为0。

另外,字符串组成不用中文的话会更节省空间。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qg2jamda-1689078910349)(Java笔记.assets/image-20230627115725232.png)]

  1. String对象的创建

    public class Demo01 {
        public static void main(String[] args) {
            System.out.println("-----------------[1] String 对象的创建----------------");
            String timber1 = new String("timber啊");
            String timber2 = "timber啊";
            String s1 = "";//在内存中开辟空间,但内容为空
            String s2 = null;//在内存中没有开辟空间      
    
        }
    }
    
  2. String最简单的方法

    public class Demo01 {
        public static void main(String[] args) {
            System.out.println("-----------------[2] String 最简单方法----------------");
            System.out.println(timber1.length());//字符串的长度
            System.out.println(timber1.startsWith("ti"));//判断字符串的开头
            System.out.println(timber1.endsWith("啊"));//判断字符串的结尾
            System.out.println(timber1.isEmpty());//判断字符串是否为空
            System.out.println(timber1.toUpperCase());//将字符串大写
            System.out.println(timber1.toLowerCase());//将字符串小写
        }
    }
    
    //输出
    -----------------[2] String 最简单方法----------------
    7
    true
    true
    false
    TIMBER啊
    timber啊
    
  3. String常用方法

    public class Demo01 {
        public static void main(String[] args) {
            System.out.println("-----------------[3] String 常用方法----------------");
            System.out.println(timber1.charAt(2));//取出第x个字符
            System.out.println(timber1.substring(0,6));//表示下标[A,B)的字符串的截取
    
            System.out.println(timber1.indexOf(98));//ASCII码为98的字符的下标,98对应的是b【不常用】
            System.out.println(timber1.indexOf('b'));//与上面方法等价【常用】
            System.out.println(timber1.indexOf("b"));//与上面方法等价【常用】
            System.out.println(timber1.indexOf("ber"));//不管字符串写多长,只会返回第一个字符的
            System.out.println(timber1.indexOf("br"));//字符不存在,返回-1
            System.out.println(timber1.indexOf("e",2));//返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
            System.out.println(timber1.lastIndexOf("i"));//返回改字符最后一次出现的下标
        }
    }
    
    //输出
    -----------------[3] String 常用方法----------------
    m
    timber
    3
    3
    3
    3
    -1
    4
    1
    
    • indexOf(int ch):返回指定字符(ASCII码)在此字符串中第一次出现处的索引。
    • indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。
    • lastIndexOf(int ch):返回指定字符在此字符串中最后一次出现处的索引。

    可以多查一下API手册

  4. String的应用

    如:将图片地址重命名为:xxx.后缀

    public class Demo01 {
        public static void main(String[] args) {
            System.out.println("-----------------[4] String 的应用----------------");
            //将图片地址改为xxx.后缀
            System.out.println("请输入图片地址:");
            Scanner scanner = new Scanner(System.in);
            String next = scanner.next();
            int i = next.lastIndexOf(".");
            String substring = next.substring(i);//获取.xxx,图片的后缀名
            String str = UUID.randomUUID().toString();//生成随机字符串,作为图片的名称
            String fileName = str + substring;
            System.out.println(fileName);
    
        }
    }
    
    //输出
    -----------------[4] String 的应用----------------
    请输入图片地址:
    637.jpg
    523b870d-4533-460f-8bb3-6c01bde91fb0.jpg
    
  5. String其他常用方法

    • String字符串转为byte数组:

      /**
       * 作者:whl
       * 日期:2023-06-26 15:39
       * 描述:中文乱码处理
       */
      public class Demo02 {
          public static void main(String[] args) throws UnsupportedEncodingException {
              String str = "timber";
              //主要作用是对中文乱码进行处理,对字符串进行重新编码
              //如:将ISO-8859-1编码,转为UTF-8编码
              byte[] bytes = str.getBytes("ISO-8859-1");
              String string = new String(bytes, "UTF-8");
              System.out.println(string);
      
          }
      }
      
      
    • String的分割:

      public class Demo03 {
          public static void main(String[] args) {
              String str = "t-i-m-b-e-r";
              String[] split = str.split("-");//以-作为分割
              System.out.println(Arrays.toString(split));
          }
      }
      
      //输出
      [t, i, m, b, e, r]
      
    • 判断某一个元素是否存在:

      public class Demo04 {
          public static void main(String[] args) {
              String timber = new String("timber");
              boolean flag = timber.contains("im");
              System.out.println(flag);
          }
      }
      
      //输出
      true
      
    • 字符替换

      • replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
      • replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
      public class Demo05 {
          public static void main(String[] args) {
              String str = new String("TimberWillTimber");
              String newStr1 = str.replaceFirst("Timber", "***");
              String newStr2 = str.replaceAll("Timber", "***");
              System.out.println(newStr1);
              System.out.println(newStr2);
          }
      }
      
      //输出
      ***WillTimber
      ***Will***
      

      例子:恶意字符替换

      public class Demo06 {
          public static void main(String[] args) {
              System.out.println("请输入:");
              Scanner scanner = new Scanner(System.in);
              String next = scanner.next();//用户输入的内容
              boolean b = next.contains("大傻逼");
              if (b){
                  String s = next.replaceAll("大傻逼", "小可爱");
                  System.out.println(s);
              }else {
                  System.out.println(next);
              }
          }
      }
      

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HegT6cG7-1689078910350)(Java笔记.assets/image-20230626164455792.png)]

    • 去除字符串中的空格

      可能会在一些业务中涉及到。

      trim():返回字符串的副本,忽略前导空白和尾部空白。

      public class Demo07 {
          public static void main(String[] args) {
              //去除字符串首尾空格
              String s = new String(" tim   be r   ");
              System.out.println(s.trim());
              //字符串的比较方法
              
          }
      }
      
      //输出
      tim   be r
      
    • 比较字符

      应用:红黑树的底层比较

      compareTo(String anotherString):按字典顺序比较两个字符串。区分大小写

      • 比较,第一个不同字符的ASCII码差值(conpareTo的左边减去右边)
      • 如果一个字符串是另一个的子串,就比较长度(conpareTo的左边减去右边)
      public class Demo07 {
          public static void main(String[] args) {
              //字符串的比较方法
              String str1 = "abc";
              String str2 = "ab";
              System.out.println(str1.compareTo(str2));
          }
      }
      
      //输出
      1
      

      compareToIgnoreCase(String str):按字典顺序比较两个字符串,不考虑大小写

      public class Demo07 {
          public static void main(String[] args) {
              //字符串的比较方法
              String str1 = "abc";
              String str2 = "AB";
              System.out.println(str1.compareTo(str2));//区分大小写
              System.out.println(str1.compareToIgnoreCase(str2));//不区分大小写
          }
      }
      
      //输出
      32
      1
      
    • 字符串的拼接方法

      两种方法底层一样,每拼接一次,底层会产生一个新的数组对象,非常浪费堆内存资源

      public class Demo08 {
          public static void main(String[] args) {
              String s1 = "ok";
              String s2 = "hello";
              System.out.println(s1 + s2);//方法1
              System.out.println(s1.concat(s2));//方法2
              System.out.println(s1.concat(s2).concat(s1));
          }
      }
      
      //输出
      okhello
      okhello
      okhellook
      

StringBuilder

  • 在字符串的拼接中,StringBuilder比String更高效。
public class Demo09 {
    public static void main(String[] args) {
        String str = "timber";
        StringBuilder builder = new StringBuilder("timber");
        long l = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++) {
//            str.concat("will");
            builder.append("will");
        }
        long e = System.currentTimeMillis();
        System.out.println("代码运行时间:" + (e-l));
    }

}
//String输出
代码运行时间:34
//StringBuilder输出
代码运行时间:20
  • 而且,StringBuilder在拼接的时候没有产生新数组,而是在原有的基础上进行添加的。
  • StringBuilder可以连续进行累加。
public class Demo10 {
    public static void main(String[] args) {
        StringBuilder timber = new StringBuilder("timber");
        StringBuilder append = timber.append("will").append("ok").append("hello");
        System.out.println(timber.hashCode());
        System.out.println(append.hashCode());
    }

}
//输出
356573597
356573597
  • insert(int offSet, ...),在字符串的指定下标添加内容
public class Demo11 {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("timber");

        builder.insert(2, "will");
        System.out.println(builder);
    }
}
//输出
tiwillmber
  • setCharAt(int offSet, char s):替换指定下标字符
public class Demo11 {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("timber");
        builder.insert(2, "will");
        System.out.println(builder);

        builder.setCharAt(3,'a');
        System.out.println(builder);
    }
}
//输出
tiwillmber
tiwallmber
  • replace(int start, int end, String str):使用给定 String 中的字符替换此序列的子字符串中的字符。注意Java中的很多区间都是左闭右开的[start,end),此处也是
//输出
public class Demo11 {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("timber");
        builder.insert(2, "will");
        System.out.println(builder);

        builder.setCharAt(3,'a');
        System.out.println(builder);

        builder.replace(1,3,"ok");
        System.out.println(builder);
    }
}
//输出
tiwillmber
tiwallmber
tokallmber
  • delete(int offSet):删除指定位置字符。
  • delete(int start, int end):删除给定区间的字符(左闭右开)。
public class Demo11 {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("timber");
        builder.insert(2, "will");
        System.out.println(builder);

        builder.setCharAt(3,'a');
        System.out.println(builder);

        builder.replace(1,3,"ok");
        System.out.println(builder);

        builder.deleteCharAt(0);
        System.out.println(builder);
    }
}
//输出
tiwillmber
tiwallmber
tokallmber
okallmber
public class Demo11 {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("timber");
        builder.insert(2, "will");
        System.out.println(builder);

        builder.setCharAt(3,'a');
        System.out.println(builder);

        builder.replace(1,3,"ok");
        System.out.println(builder);

        builder.deleteCharAt(0);
        System.out.println(builder);

        builder.delete(5,8);
        System.out.println(builder);
    }
}
//输出
tiwillmber
tiwallmber
tokallmber
okallmber
okallr
  • reverse():倒序。
public class Demo11 {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("timber");
        builder.insert(2, "will");
        System.out.println(builder);

        builder.reverse();
        System.out.println(builder);
    }
}

//输出
tiwillmber
rebmlliwit
String和StringBuilder的相互转化

一般不用,了解即可。

public class Demo12 {
    public static void main(String[] args) {
        //String转StringBuilder
        String str = "timber";
        StringBuilder builder = new StringBuilder(str);

        //StringBuilder转String
        String string = builder.toString();

    }

}

StringBuffer

与StringBuilder相似度高达99%。

解释下线程安全
  • 线程安全:可以比作排队一个一个的出去,很安全,但是效率低。
  • 线程不安全:可以比作一窝蜂出去,可能一次出去5个,也可能10个等等,效率高,但是容易出现事故。

在Java中不存在既安全,又效率高的结构

StringBuffer和StringBuilder的主要区别:

  • StringBuffer:jdk1.0提供的类,线程安全,做线程同步检查,效率较低。
  • StringBuilder:jdk1.5提供的类,线程不安全,不做线程同步检查,因此效率较高,建议采用该类。

使用原则

  1. 只要不涉及字符串拼接,就用String,各种方法都很全。
  2. 一旦涉及字符串拼接,就用StringBuilderStringBuffer几乎不用。而StringBuilder中几乎只用append()方法,其他基本用不上。
思考(涉及源码)

问题:字符串拼接是的底层是数组,数组的长度一旦固定就不能改变了,StringBuilder的追加是在原来的基础上进行的,那StringBuilder是怎么做到的呢?

不是不会产生新数组,而是不会频繁的产生新数组。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xJKasGJU-1689078910351)(Java笔记.assets/image-20230628142459226.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xjq9l87P-1689078910351)(Java笔记.assets/image-20230628142638347.png)]

创建StringBuilder对象的时候,底层会自动产生一个长度为16的数组value。(这个16不是平白无故得来的,是经过压力测试的,为16时效率最高)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UFrQxUMf-1689078910352)(Java笔记.assets/image-20230628143109385.png)]

public class Demo12 {
    public static void main(String[] args) {
        String str = "timber";
        StringBuilder builder = new StringBuilder(str);//有参构造中的数组长度为,传入字符串长度6+16
    }
}
  • 查看底层数组的长度用.capacity()

  • 扩容的大小是,在原来的基础上乘以2,再加2,即:2n+2。

public class Demo13 {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("haha");
        System.out.println("底层数组长度:" + builder.capacity());//创建后为4+16
        for (int i = 0; i < 16; i++) {
            builder.append("a");
        }
        System.out.println("底层数组长度:" + builder.capacity());//未超过容量20
        builder.append("a");
        System.out.println("底层数组长度:" + builder.capacity());//超过容量,进行扩容:20*2+2 = 42
        for (int i = 0; i < 21; i++) {
            builder.append("a");
        }
        System.out.println("底层数组长度:" + builder.capacity());//未超过容量42
        builder.append("a");
        System.out.println("底层数组长度:" + builder.capacity());//超过容量,进行扩容: 42*2+2 = 86
    }
}
//输出
底层数组长度:20
底层数组长度:20
底层数组长度:42
底层数组长度:42
底层数组长度:86
  • 扩容完的长度也不够追加的,该怎么办?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eTJ9VkVI-1689078910352)(Java笔记.assets/image-20230628150543272.png)]

public class Demo14 {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder("haha");
        System.out.println("底层数组长度:" + builder.capacity());//创建后为4+16=20
        for (int i = 0; i < 50; i++) {
            builder.append("a");//42,86
        }
        System.out.println("底层数组长度:" + builder.capacity());//

    }
}
//输出
底层数组长度:20
底层数组长度:86

String中常见面试题

StringBufferStringBuilder不常问,问也是问扩容。String问的比较多。

例1

public class InterviewTest {
    public static void main(String[] args) {
        String a = "a";
        String b = "b";
        String c = "c";
        String d = "d";

        String s1 = a + b + c + d;//(3个)相当于new了3个变量:"ab","abc","abcd"
        String s2 = "abcd";//(1个/0个)常量池中没有,就创建一个;有就指向已有的常量池
        String s3 = "a" + "b" + "c" + "d";//(1个/0个)JVM自动优化,当作"abcd"来处理
        //s1和s3的区别是,+的是常量还是变量,+变量就是new,+常量就不用

        System.out.println(s1 == s2);
        System.out.println(s2 == s3);
        System.out.println(s1 == s3);
    }
}
//输出
false
true
false

例2

public class InterviewTest2 {
    public static void main(String[] args) {
        String s0 = "5";
        String s1 = "52";
        String s2 = "5" + "2";
        String s3 = "5" + 2;//常量的+是一样的
        String s4 = s0 + 2;//new了

        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s1 == s4);
    }
}
//输出
true
true
false

Date类

在计算机中,把1970年1月1日的00:00:00定为基准时间,每个度量单位是毫秒

工作学习中涉及的类有以下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RxPfZtsa-1689078910353)(Java笔记.assets/image-20230628160419146.png)]

关于年(year)的度量是从1900年开始的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wy96H6Xd-1689078910353)(Java笔记.assets/image-20230628161133296.png)]

java.util.Date

以2023.06.28为例,注意包名为java.util.Date

  • getYear()从1900年开始算,2023年则输出123。
  • getMonth():一年中的第几个月,从0开始,6月输出5。
  • getDate():这个月中的第几天
  • getDay():一周中的第几天,星期几
  • getHours():时
  • getMinutes():分
  • getSeconds():秒
  • toLocalString():xx年xx月xx日 xx:xx:xx
public class Demo01 {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date.getYear());
        System.out.println(date.getMonth());
        System.out.println(date.getDate());
        System.out.println(date.getDay());
        System.out.println(date.getHours());
        System.out.println(date.getMinutes());
        System.out.println(date.getSeconds());
        System.out.println(date.toLocaleString());
    }

}
//输出
123//年
5//月
28//日
3//星期三
16//16点
28//28分
25//25秒
2023-6-28 16:40:44

用毫秒数统计代码的效率,从1970年开始算。(代码的输出也是需要时间的,所以前后语句输出的毫秒数会有差距)

package com.systemcla.date;

import java.util.Date;

/**
 * 作者:whl
 * 日期:2023-06-28 16:37
 * 描述:毫秒
 */
public class Demo02 {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date.getTime());
        System.out.println(System.currentTimeMillis());
    }
}

//输出
1687941490439
1687941490440

在应用中为了使订单号不重复,除了使用获得毫秒的方法,还可以使用uuid的方法。除了毫秒,还有纳秒,重复的概率就更低了。

归纳毫秒作用

  1. 统计代码执行时间。
  2. 用作唯一标识。
java.sql.Date

属于java.util.Date的子类。使用sql.Date可以进行日期转换。

java.util.Date √ (既可以获得年月日,又可以获得时分秒)

​ java.sql.Date √ (只可以获得年月日)

​ java.sql.Time (只可以获得时分秒)

​ java.sql.TimeStamp (时间戳,年月日 时分秒)

  • 重要方法:将String类型字符串转为日期格式(但是,只支持yyyy-MM-dd形式的转化,即:只可以转含有年月日的格式,不可以携带时分秒)
package com.systemcla.date;

import java.sql.Date;

/**
 * 作者:whl
 * 日期:2023-06-28 19:21
 * 描述:
 */
public class Demo03 {
    public static void main(String[] args) {
        String str = "2023-06-28";
        Date date = Date.valueOf(str);
        System.out.println(date);

    }
}
//输出
2023-06-28
DateFormat类

把指定格式的字符串转为时间对象。该类为抽象类,不能new,子类只有一个SimpleDateFormat

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wi8P5rkR-1689078910354)(Java笔记.assets/image-20230628201435283.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QTk5qfoO-1689078910354)(Java笔记.assets/image-20230628201459279.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYYuYmm0-1689078910355)(Java笔记.assets/image-20230628203259611.png)]

  • H和h的区别是,H是24小时制的,h是12小时制的。
  • M是月,m是秒。
  • D是年中的第几天,d是月中的第几天。
  • S是毫秒,s是分钟中的秒。

注意:类型转化中,SimpleFormat中的格式和String类型的要对应。

package com.systemcla.date;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 作者:whl
 * 日期:2023-06-28 20:11
 * 描述:Date类
 */
public class Demo04 {
    public static void main(String[] args) throws ParseException {
        //String转Date
        String str = "2023-06-28 20:35:06";
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = dateFormat.parse(str);
        System.out.println(date);

        String str2 = "2023/06/28 20:35:06";
        DateFormat dateFormat2 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date2 = dateFormat.parse(str);
        System.out.println(date2);

        String str3 = "2023年06月28日 20:35:06";
        DateFormat dateFormat3 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date date3 = dateFormat.parse(str);
        System.out.println(date3);

        //Date转String
        Date date1 = new Date();
        DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String s = format1.format(date1);
        System.out.println(s);
    }
}
//输出
Wed Jun 28 20:35:06 CST 2023
Wed Jun 28 20:35:06 CST 2023
Wed Jun 28 20:35:06 CST 2023
2023-06-28 20:49:17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值