Java后端高频面试知识点汇总(2):Java基础

目录

一、String、StringBuilder和StringBuffer的区别是什么?

(1) String是不可变的,StringBuilder和StringBuffer是可变的

(2) String和StringBuffer是线程安全的,StringBuilder不是线程安全的。

(3)执行效率方法:StringBuilder最高,StringBuffer次之,String最低。

对于三者使用的总结:

二、String不可变的好处

 三、自动装箱与拆箱

包装类:

装箱:将基本类型用它们对应的引用类型包装起来。

拆箱:将包装类型转化为基本数据类型。

new Integer(123) 与 Integer.valueOf(123) 的区别在于:

四、Java Object类中的方法

五、反射

5.0 类加载器

5.1 什么是反射?

5.2 反射机制的优缺点有哪些?

5.3 如何获取反射中的Class对象?

1. Class.forName(“类的路径”);当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。

2. 类名.class。这种方法只适合在编译前就知道操作的 Class。

3. 对象名.getClass()。

4. 如果是基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象。

六、Java创建对象的5种方式?

六、泛型


一、String、StringBuilder和StringBuffer的区别是什么?

1. 可变性

  • String 不可变
  • StringBuffer 和 StringBuilder 可变

2. 线程安全

  • String 不可变,因此是线程安全的
  • StringBuilder 不是线程安全的
  • StringBuffer 是线程安全的,内部使用 synchronized 进行同步

(1) String是不可变的,StringBuilder和StringBuffer是可变的

  • String是不可变的,String类中使用final关键字修饰char字符数组来保存字符串,private final char value[],从Java9开始,String类的实现改用byte字节数组存储字符串private final byte[] value
  • 而StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串char[] value但是没有用final关键字修饰,所以这两种对象都是可变的。

(2) String和StringBuffer是线程安全的,StringBuilder不是线程安全的。

  • String中的对象的不可变的,所以是线程安全。
  • StringBuffer对方法加了synchronized同步锁,所以是线程安全的。
  • StringBuilder没有对方法加同步锁,所以不是线程安全的。

(3)执行效率方法:StringBuilder最高,StringBuffer次之,String最低。

每次对String类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象。StringBuffer每次都会对StringBuffer本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StringBuilder相比使用StringBuffer仅能获得10%~15%左右的性能提升,但要冒多线程不安全的风险。

对于三者使用的总结:

当操作少量数据时,优先使用String。

当在单线程下操作大量数据,优先使用StringBuilder类

当在多线程下操作大量数据,优先使用StringBuffer类

二、String不可变的好处

1. 可以缓存 hash 值

因为 String 的 hash 值经常被使用,例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变,因此只需要进行一次计算。

2. String Pool 的需要

如果一个 String 对象已经被创建过了,那么就会从 String Pool 中取得引用。只有 String 是不可变的,才可能使用 String Pool。

3. 安全性

String 经常作为参数,String 不可变性可以保证参数不可变。例如在作为网络连接参数的情况下如果 String 是可变的,那么在网络连接过程中,String 被改变,改变 String 的那一方以为现在连接的是其它主机,而实际情况却不一定是。

4. 线程安全

String 不可变性天生具备线程安全,可以在多个线程中安全地使用。

 三、自动装箱与拆箱

包装类:

装箱:将基本类型用它们对应的引用类型包装起来。

  • 装箱的时候自动调用的是Integer的valueOf(int)方法。

拆箱:将包装类型转化为基本数据类型。

  • 拆箱的时候自动调用的是Integer的intValue方法。

new Integer(123) 与 Integer.valueOf(123) 的区别在于:

  • new Integer(123) 每次都会新建一个对象;
  • Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用
Integer x = new Integer(123);
Integer y = new Integer(123);
System.out.println(x == y);    // false
Integer z = Integer.valueOf(123);
Integer k = Integer.valueOf(123);
System.out.println(z == k);   // true

在 Java 8 中,Integer 缓存池的大小默认为 -128~127。

四、Java Object类中的方法

  • getClass() 返回一个对象的运行时类。 
  • int hashCode() 返回该对象的哈希码值。 
  • boolean equals(Object obj) 指示某个其他对象是否与此对象“相等”。 
  • String toString() 返回该对象的字符串表示。 
  • void notify() 唤醒在此对象监视器上等待的单个线程。 
  • void notifyAll() 唤醒在此对象监视器上等待的所有线程。 
  • void wait() 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。 
  • protected Object clone() 创建并返回此对象的一个副本。 
  • protected void finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。 

五、反射

5.0 类加载器

是负责将磁盘上的某个class文件读取到内存并生成Class的对象。

类的加载时机:

  1.  创建类的实例。
  2.  类的静态变量,或者为静态变量赋值。
  3.  类的静态方法。
  4.  使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。
  5.  初始化某个类的子类。
  6.  直接使用java.exe命令来运行某个主类。

以上六种情况的任何一种,都可以导致JVM将一个类加载到方法区。

public class Test {
    public static void main(String[] args) throws Exception{
        // 类的加载时机
        //  1. 创建类的实例。
         Student stu = new Student();

        // 2. 类的静态变量,或者为静态变量赋值。
         Person.country = "中国";

        // 3. 类的静态方法。
         Person.method();

        // 4. 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。
         Class<?> c = Class.forName("com.itheima.demo1_类的加载.Student");

        //  5. 初始化某个类的子类。
         Zi zi = new Zi();

        // 6. 直接使用java.exe命令来运行某个主类。
    }
}

5.1 什么是反射?

反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为 Java 语言的反射机制

反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖,并操作类中的所有成员(成员变量,成员方法,构造方法)

Class 和 java.lang.reflect 一起对反射提供了支持,java.lang.reflect 类库主要包含了以下三个类:

  • Field :可以使用 get() 和 set() 方法读取和修改 Field 对象关联的字段;
  • Method :可以使用 invoke() 方法调用与 Method 对象关联的方法;
  • Constructor :可以用 Constructor 的 newInstance() 创建新的对象。

5.2 反射机制的优缺点有哪些?

  • 优点:能够运行时动态获取类的实例,提高灵活性;可与动态编译结合 Class.forName('com.mysql.jdbc.Driver.class') ,加载MySQL的驱动类。
  • 缺点:使用反射性能较低,需要解析字节码,将内存中的对象进行解析。其解决方案是:通过 setAccessible(true)关闭JDK的安全检查来提升反射速度;多次创建一个类的实例时,有缓存会快很多; ReflflectASM工具类,通过字节码生成的方式加快反射速度。

5.3 如何获取反射中的Class对象?

1. Class.forName(“类的路径”);当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。

Class clz = Class.forName("java.lang.String");

2. 类名.class。这种方法只适合在编译前就知道操作的 Class。

Class clz = String.class;

3. 对象名.getClass()。

String str = new String("Hello");
Class clz = str.getClass();

4. 如果是基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象。

六、Java创建对象的5种方式?

  1. 使用new关键字
  2. 使用Class类的newInstance方法
  3. 使用Constructor类的newInstance方法
  4. 使用clone方法
  5. 使用反序列化

六、泛型

定义的时候表示一种未知的数据类型,在使用的时候确定其具体的数据类型。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

Java的泛型即“参数化类型”,允许程序在创建集合时指定集合元素的类型,表明该集合只能保存该类型的对象。

如果不使用泛型,当把一个对象存入集合后,集合就会忘记这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了Object类型,还需要进行强制转换。

当使用泛型后,集合中是能存入集合指定类型的对象,否则将报错。并且将对象从集合取出后无需对元素进行强制转换,就是原本的类型。

在集合中存储对象并在使用前进行类型转换是多么的不方便。泛型防止了那种情况的发生。它提供了编译期的类型安全,确保你只能把正确类型的对象放入集合中,避免了在运行时出现ClassCastException。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值