Java基础集合多线程JVM

Java基础 重点记录 构造器 Constructor 是否可被 override? Constructor 不能被 override(重写),但是可以 overload(重载),所以你可以看到一个类中有多 个构造函数的情况。 重载和重写的区别 重载就是同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。 重写就是子类对父类方法的重新改造,外部样子不能改变,内部逻辑可以改变。 重写发生在运行时。因为在编译时,编译器是无法知道我们到底是调用父类的方法还是子类的方法,相反的,只有在实际运行的时候,我们才知道应该调用哪个方法。 重载发生在编译时。在编译过程中,编译器必须根据参数类型以及长度来确定到底是调用的哪个方法,这也是Java编译时多态的体现。 Java 面向对象编程三大特性: 封装 继承 多态 继承 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是⽆法访问,只是拥有。 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。 子类可以用自己的方式实现父类的方法。(以后介绍)。 多态 多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作(调用同一个方法)。 在 Java 中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。 StringBuffer 和 StringBuilder 的区别是什么? String 为什么是不可变的? 简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串, private final char value[] ,所以 String 对象是不可变的。 StringBuffer 对方法加了同步锁synchronized或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。 StringBuffer/StringBuilder 每次都会对对象本身进行操作,而不是像String生成新的对象并改变对象引用。 相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。 在 Java 中定义一个不做事且没有参数的构造方法的作用 规定:Java 程序在执行子类的构造方法之前,如果没有用 super() 来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。 因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用 super() 来调用父类中特定的构造方法,则编译时将发生错误,因为 Java 程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。 ...

January 22, 2025 · 10 min

StringPool(字符串常量池)

字符串常量池的解释 字符串常量池(String Pool)保存着所有字符串字面量(literal strings),这些字面量在编译时期就确定哪些是要放入字符串常量池。具体来说,只有使用双引号("")创建的字符串字面量才会被认为是常量,从而被放入常量池中。 在运行时,还可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中。调用该方法会判断字符串常量池是否有该字面量,如没有,会在字符串常量池创建。之后,会返回字符串常量池中的对象。 通过new创建的字符串字面量,会先将,无论是否在字符串常量池存在,都会创建新的对象且不放入字符串常量池。 String str1 = "Hello world!"; String str2 = "Hello world!"; String str3 = new String("Hello world!"); String str4 = new String("Hello world!"); String str5 = str4.intern();//运行过程中把字符串添加到String Pool,并返回String Pool中的对象 System.out.println(str1 == str2);//运行结果:true。 System.out.println(str1 == str3);//运行结果:false。 System.out.println(str3 == str4);//运行结果:false。 System.out.println(str1 == str5);//运行结果:true。 System.out.println(str4 == str5);//运行结果:false。 字符串常量池长度 在 jdk6中,StringTable的长度是固定的,就是1009的长度。所以如果常量池中的字符串过多,会产生hash冲突,导致链表变长,降低查询效率。 在jdk7中,StringTable的长度可以通过一个参数指定: -XX:StringTableSize=99991 字符串常量池的位置 不同版本的Java虚拟机(JVM)可能会采用不同的方式来实现字符串常量池,并且在不同的JVM实现中,字符串常量池的位置也可能会发生变化。 JDK 6 字符串常量池存在于运行时常量池,运行时常量池存在方法区。方法区的实现为永久代(PermGen)。 PermGen默认大小只有4m,这种设计可能会导致PermGen空间溢出(java.lang.OutOfMemoryError: PermGen space)的问题,并且在频繁加载大量类文件时容易出现性能问题。 JDK 7 为了解决这些问题,从 JDK 7 开始,字符串常量池被移动到了堆内存中。 JDK 8 还是在堆内存中。 字符串的拼接 如果定义字符串时有拼接的表达式,编译器会根据表达式的参数是否为"“直接引用来判断是否将字符串字面量放入字符串常量池。 如表达式"Hello”+" world!",编译器会将两个字符串拼接成一个新的字符串"Hello world!",然后对比这个新字符串对象和常量池中的字符串字面量"Hello world!“是否相同。由于Java字符串常量池的特性,当两个字符串的内容相同时,它们所引用的字符串对象实例也是相同的。因此,表达式"Hello”+" world!" == “Hello world!“的结果为true。 ...

January 9, 2025 · 2 min