Java 面试题

java面试题 当线程 A 持有独占锁a,并尝试去获取独占锁 b 的同时,线程 B 持有独占锁 b,并尝试获取独占锁 a 的情况下,就会发生 AB 两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁。反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。Java 序列化是为了保存各种对象在内存中的状态,并且可以把保存的对象状态再读出来。 阅读详情

Java 面试题

1、Java都有哪些特点?

  1. 简单易学,容易学习和理解。
  2. 面向对象,支持封装,继承,多态等面向对象的特点
  3. 跨平台性,可以做到一段代码,在不同的平台上运行,只要对应的平台安装 Java虚拟机
  4. 内存自动回收机制,做到不需要手动释放内存,Java 使用垃圾回收器管理内存,减少了内存泄漏等情况
  5. 高性能,通过 JIT 即时编译器,将热点的字节码转换为机器码,提高了代码执行的效率
  6. 具有丰富的 AIP 社区,很多开源的 AIP 可以使用

2、面向对象和面向过程的区别?

  1. 面向对象是以对象为基础的编程方式,将数据和函数封装到一起,形成一个对象的实体,面向对象强调的是对象与对象之间的消息通讯,通过定义类和创建对象实现程序的设计和开发。面向对象编程适合解决复杂的问题,将抽象的问题用具体的对象的调用来解决。利用对象解决问题,可以更好的组织和管理代码,提高代码的复用性和可维护性。
  2. 面向过程是以函数为基础的编程方式,将问题拆分为一定的步骤和函数的调用,通过定义函数和全局变量等来实现设计和开发,面向过程更直观,用于简单问题和小型的项目。

3、八种基本数据类型和对应的大小,以及他们的封装类?

  1. 整型:
    1. byte: 1 字节 Byte
    2. shout: 2 字节 Shout
    3. int: 4 字节 Integer
    4. long 8 字节 Long
  2. 浮点型:
    1. float: 4 字节 Float
    2. double: 8 字节 Double
  3. 字符型:
    1. char: 2 字节 Character
  4. 布尔型
    1. boolean: - Boolean (单独:4 字节,在数组中:1 字节)

4、标识符和命名规则?

  • Java 中的标识符使用来标识变量名、方法名、类名、包名等
    • 只能由数字、字母、下划线、美元符号组成
    • 不能以数字开头
    • 标识符严格区分大小写
    • 标识符不能是关键字(class、public)或保留字(goto)或特殊的值(true、false)
    • 标识符要有具体的描述,要做到见名知意

5、重载和重写的区别?

  • 重载是指在同一个作用域下定义了多个同名的方法,但这些方法参数的种类、数量、顺序不同,编译器可以区分这些方法,重载方法可以提高代码的可读性和灵活性。(两同:同一个类,方法名相同)
  • 重写是重新定义了从父类中继承而来的方法,实现了多态性,即,父类的引用指向子类的对象,调用父类的方法时,执行的是子类中重写的方法。

6、equals与==的区别?

  • equal() 用于比较对象的内容是否相等,在对象没有重写的情况下,默认比较的是地址,只有重写了equal() 方法才会比较内容是否相同。
  • == 对于基本数据类型是比较值,对于引用数据类型是比较对象的地址是否相同,如果两个对象指向同一个内存地址,那么就认为这两个对象相同。

7、Hashcode的作用?

  • hashCode是对象的一个方法,用于计算对象在hash表中的位置
  • 在集合的查找和存储中,hashCode用于快速查询和储存对象,在使用hashMap等集合类时就可以快速的确定存储位置和查找位置,提高代码的运行效率。
  • 对象的判断,两个对象相同,那这两个对象的hash值一定相同,但是,因此可以先比较hash值,如果hash值不相同,这两个对象一定不相同,如果相同,再用equal()判断

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

  • String:

    • 不可变的,在对String进行操作时,都会创建一个新的对象,对系统的开销很大

    • 线程安全

    • jdk7 时,Spring常量池在永久代,到 jdk8 及以后,Spring常量池被转移到了堆内存中

      • 当使用 Stirng str = “AA”; 时,“AA”会被储存在常量池中,因此,当再次创建“AA”时,不会在创建一个新的字符串,而是引用常量池中存在的字符串。

                String str1 = new String("Hello"); //new出来的都堆中,不会进入常量池
                String str2 = "Hello";
                System.out.println(str1 == str2);  //false
        
        
                String str3 = "Hello";  //进入常量池
                String str4 = "Hello";  //引用常量池中的数据
                System.out.println(str3 == str4);  //true
        
                String str5 = new String("Hello");  //进入堆空间,开辟一块空间放入字符串
                String str6 = new String("Hello");  //进入堆空间,开辟一块空间放入字符串
                System.out.println(str5 == str6);  //false
        
  • StringBuffer

    • 可变的,可以在原来的基础上进行修改
    • 线程安全的,所有的公开方法都用synchronized
  • StringBuilder

    • 可变的
    • 非线程安全的

9、ArrayList和LinkedList的区别?

  • AllayList:
    • 底层使用数组进行储存,当超出数组的范围时,会自动扩容 1.5 倍。
    • 由于用利用数组进行储存,查询效率高,但是删除和插入效率低
  • LinkedList:
    • 底层使用双向链表实现的,每个节点包含前一个节点和后一个节点的引用。
    • 由于利用链表进行储存,删除和插入效率高,查询的效率低

10、HashMap和HashTable的区别?

  • hashMap:
    • 底层使用数组+链表+红黑树
    • 线程不安全
    • 允许null键和null值
    • 当hashMap不足时,会进行扩容,默认扩容为原来的 2 倍(因为通过二次hash值计算位置时方便)

11、List,Set,Map三者的区别?

  1. List:
    - List是一个有序的集合,可以包含重复的元素。
    - List允许通过索引访问元素,可以根据元素的位置进行增删改查操作。
    - 常见的List实现类有ArrayList和LinkedList。

  2. Set:
    - Set是一个不允许包含重复元素的集合。
    - Set不保证元素的顺序,即不按照插入顺序或者排序顺序进行存储。
    - Set提供了判断元素是否存在的方法,可以用于去重。
    - 常见的Set实现类有HashSet和TreeSet。

  3. Map:

    • Map是一种键值对的映射表,每个键对应一个值。
      • Map中的键是唯一的,但值可以重复。
      • Map提供了根据键获取值的方法,也可以根据键删除或更新对应的值。
      • 常见的Map实现类有HashMap和TreeMap。

12、Collection包结构,与Collections的区别?

  • Collection是集合类的上级接口。
  • Collections里面封装了有关集合操作的静态方法

13、Java的四种引用,强弱软虚?

  • **强引用:**这是最常见的引用类型,如果一个对象具有强引用,垃圾回收器绝不会回收它,当内存不足时,宁愿抛出错误终止程序,也不会随意

    ​ 回收具有强引用对象来解决内存不足问题。

  • **软引用:**用来描述一些还有用,但是并非必须的对象,将要发生内存溢出异常之前,将会把这些对象列进回收的范围中进行二次回收。

  • **弱引用:**弱引用也是用来描述非必需对象的,但是它的强度比软引用更弱一些,当垃圾回收器工作时,都会回收掉只被弱引用关联的对象

  • **虚引用:**最弱的引用关系,完全不会对其生存时间构成影响,唯一目的就是在这个对象被回收时,收到一个系统通知

14、泛型常用特点?

  • 泛型可以在定义类或接口的时候表示类型,在创建对象的时候指定类型
  • 提高代码的复用性和可维护性。
  • 提高代码的运行效率,泛型在编译时会进行类型擦除,减少运行时的开销,避免了装箱和拆箱的操作

15、Java创建对象有几种方式?

  1. 关键字 new 创建新对象
  2. 通过反射机制
  3. 采用clone机制
  4. 通过序列化机制

16、深拷贝和浅拷贝的区别是什么?

  • 深拷贝,就是创建一个新的对象,新对象将原来对象中的所有信息全部复制下来,如果是引用数据类型,会重新创建对象,然后放入值
  • 浅拷贝,创建一个对象,复制对象的属性,如果属性是引用数据类型,就只是引用原数据,不会创建对象。

17、final有哪些用法?

  • final修饰类,表示该类是最终类,不会被继承,没有子类
  • final修饰方法,表示该方法是最终方法,不能被子类重写
  • final修饰变量,表示该变量是常量,一旦复制,不可被改变
  • final修饰引用数据类型,该数据类型的地址不可变,但是其中的属性可变
  • final修饰参数,表示该方法内,该参数不可变

18、static都有哪些用法?

  1. 静态变量:使用static修饰的变量称为静态变量,也叫类变量。静态变量属于类,而不是属于类的实例。静态变量在类加载时被初始化,并且只有一份拷贝,所有实例共享该变量的值。可以通过类名直接访问静态变量。

    	//1. 静态变量:使用static修饰的变量称为静态变量,也叫类变量。静态变量属于类,而不是属于类的实例。静态变量在类加载时被初始化,并且只有一份拷贝,所有实例共享该变量的值。可以通过类名直接访问静态变量。
    
     	//2. 静态方法:使用static修饰的方法称为静态方法,也叫类方法。静态方法属于类,而不是属于类的实例。静态方法可以直接通过类名调用,无需创建类的实例。静态方法只能访问静态成员(包括静态变量和静态方法),不能访问非静态成员。
    
    	//3. 静态代码块:使用static关键字定义的代码块称为静态代码块。静态代码块在类加载时执行,并且只会执行一次。静态代码块常用于初始化静态变量或执行一些只需执行一次的操作。
    
    	//4. 静态内部类:使用static修饰的内部类称为静态内部类。静态内部类与外部类没有直接的关联,可以直接通过外部类名访问。静态内部类可以拥有自己的静态成员,但不能访问外部类的非静态成员。
    

19、有没有可能两个不相等的对象有相同的hashcode(哈希冲突) ?


20、如何解决哈希冲突?

  • 开放地址法:当发生哈希冲突时,通过一定的探测方法找到下一个可用的位置。常见的探测方法有线性探测、二次探测和双重哈希等。线性探测是指依次往后查找,直到找到一个空闲位置;二次探测是指通过二次方程计算下一个位置;双重哈希是指使用第二个哈希函数来计算下一个位置。

  • 再哈希法:当发生哈希冲突时,使用另一个哈希函数重新计算索引位置。如果仍然发生冲突,可以继续使用其他哈希函数进行再哈希,直到找到一个空闲位置。


21、Object 有哪些常用方法?方法的含义?

  1. equals(Object obj):判断当前对象是否与给定对象相等。默认情况下,equals方法比较的是对象的引用是否相等,即是否指向同一个内存地址。如果需要比较对象的内容是否相等,需要在具体类中重写equals方法。
  2. hashCode():返回当前对象的哈希码值。哈希码是根据对象的内部状态计算得出的一个整数值,用于快速查找和比较对象。在重写equals方时,通常也需要重写hashCode方法。
  3. toString():返回当前对象的字符串表示。默认情况下,toString方法返回的是对象的类名和哈希码值的组合。可以根据需要在具体类中重写toString方法,以便返回更有意义的字符串表示。
  4. getClass():返回当前对象所属的类的Class对象。Class对象包含了关于类的各种信息,可以用于获取类的名称、字段、方法等。
  5. clone():创建并返回当前对象的一个副本。默认情况下,clone方法会创建一个浅拷贝,即只复制对象的引用而不复制对象本身。如果需要实现深拷贝,需要在具体类中重写clone方法。
  6. finalize():在垃圾回收器回收对象之前调用。可以在具体类中重写finalize方法,以便在对象被销毁之前执行一些清理操作。

22、jdk、jre、jvm

  • 理解:

    1. **jvm:**Java虚拟机,是 Java 平台的核心,它使得 Java 程序可以在不同的操作系统上运行而无需编译

    2. **jre:**Java运行时环境提供了Java的核心类库(Java.long / java,util)等,如果如果只是运行Java程序,那jre就能满足

      ​ 需求。

    3. **jdk:**jdk是Java的开发包,包含编译,调试,运行Java代码的开发工具。

  • 关系:jdk 包含 jre ,jre包含jvm

  • jdk = jvm + 核心类库(java.long / java.util) + 开发工具(javac、javadoc、jdb(deBug))


23、Java是半编译、半解释的语言

  • Java 在编译阶段将源代码转换为字节码,在运行阶段又通过解释器或者即时编译器将字节码转换为机器码执行,所以说 Java 是半编译、半解释的语言。

24、注解

  • 注解是一种元数据标记,用于提供关于代码的额外信息,注解不会直接影响程序的执行,但可以被编译器、运行时环境或工具使用
  • 注解通常在类、方法或变量前使用@注解名的形式添加注解。例如,@Override 用于检查方法是否正确重写。
  • 优缺点
    • 优点:增强代码的可读性,提供元数据,支持编译时检查,简化代码编写。
    • 缺点:过度使用注解可能导致代码难以理解,某些注解可能会影响性能。

25、字符型常量和字符串常量

  • 字符型常量是单个字符,用单引号表示;字符串常量是字符序列,用双引号表示。
  • 字符常量用于表示单个字符,如 'A';字符串常量用于表示文本,如 "Hello"。
  • 优缺点
    • 优点:字符型常量和字符串常量在 Java 中是基本的数据类型,使用广泛。
    • 缺点:字符串是不可变的,频繁修改字符串内容会导致性能问题

26、标识符和关键字的区别

  • 标识符是用户自定义的名称,关键字是Java预定义的有特殊意义的词。
  • 标识符用于命名类、方法、变量等,关键字用于特定的语法结构,如 if、for 等。
  • 优缺点
    • 优点:标识符提供了灵活性,关键字提供了语言的结构。
    • 缺点:需要避免将关键字作为标识符,否则会导致编译错误。

27、自增(++)和自减(–)

  • 自增和自减是Java中的运算符,用于增加或减少变量的值。
  • ++var 或 var++ 用于自增,--var 或 var-- 用于自减。
  • 后置++或- - 是使用后就会生效,即:(i= 2) ——》a = (i + i ++) + (++i) ==> (2 + 2 ++) + (++2) ==> (4) + (++3) ==> 4 + 4 = 8
  • 优缺点
    • 优点:提供了一种简洁的方式来修改变量的值。
    • 缺点:在复杂表达式中使用时可能导致混淆。

28、泛型

  • 泛型是Java中用于支持类型参数化的一种机制,允许在类、接口和方法中使用类型参数。类型擦除是泛型的实现方式,类型擦除的设计是为了兼容那些早期不支持泛型的语言特性,开发者可以在编写代码时享受泛型带来的便利,而编译器则会在编译阶段确保类型安全,然后擦除这些类型信息以适应现有的类结构体系。

29、transient 关键字(阻止序列化)

  • 主要功能:
    • transient 关键字用于标记类的字段,使其在对象序列化过程中不被保存。
    • 这可以用于保护敏感数据(如密码)或避免序列化不必要的字段,从而提高性能和安全性。
  • 应用场景:
    • 当某些字段不需要或不应该在序列化过程中被保存时,可以使用 transient 关键字。
    • 例如,临时数据、计算结果、敏感信息等。

通过使用 transient 关键字,开发者可以更灵活地控制对象的序列化过程,确保只有必要的数据被持久化。


30、快速失败&安全失败

在Java编程当中,Iterator迭代器是一种用于遍历如List、Set、Map等集合的工具。这类集合部分存在线程安全的问题,例如ArrayList,若在多线程环境下,迭代遍历过程中存在其他线程对这类集合进行修改的话,就可能导致不一致或者修改异常问题,因此,针对这种情况,迭代器提供了两种处理策略:Fail-Fast(快速失败)和Fail-Safe(安全失败)。

先简单介绍下这两种策略——

  1. Fail-Fast(快速失败)机制
    快速失败机制是指集合在迭代遍历过程中,其他多线程或者当前线程对该集合进行增加或者删除元素等操作,当前线程迭代器读取集合时**会立马抛出一个ConcurrentModificationException异常,避免数据不一致。**实现原理是迭代器在创建时,会获取集合的计数变量当作一个标记,迭代过程中,若发现该标记大小与计数变量不一致了,就以为集合做了新增或者删除等操作,就会抛出快速失败的异常。在ArrayList默认启用该机制。

  2. Fail-Safe(安全失败)机制
    安全失败机制是指集合在迭代遍历过程中,若其他多线程或者当前线程对该集合进行修改(增加、删除等元素)操作,当前线程迭代器仍然可以正常继续读取集合遍历,而不会抛出异常。该机制的实现,是通过迭代器在创建时,对集合进行了快照操作,即迭代器遍历的是原集合的数组快照副本,若在这个过程,集合进行修改操作,会将原有的数组内容复制到新数组上,并在新数组上进行修改,修改完成后,再将集合数组的引用指向新数组,,而读取操作仍然是访问旧的快照副本,故而实现读写分离,保证读取操作的线程安全性。在CopyOnWriteArrayList默认启用该机制。


31、Hash的理解

  • hash的基本概念就是把任意长度的输入通过一个hash算法后,映射成固定长度的输出

32、Hash为什么采用高16位异或低16位

  • 优化hash算法,因为散列表的长度一般不会太大,hash值一般就用到低16位(hash & (table.length-1)),高16位没用

    因此,将高16位与低16位进行 异或 操作,让高16位也有用


33、为什么java只有值传递

  • 认识:Java中引用数据类型传递的是该对象的引用副本,在方法中,重新引用不会影响到原有对象,但是,改变对象的属性,可以影响。

  • **安全性和可预测性:**开发人员可以明确的知道方法调用的数据是否被修改,对于基本数据类型,参数的值不会被修

    改,对于引用数据类型,可以清楚的知道,引用所指向的对象的修改会影响到所有指向该对象的引用。这种设计也避免了潜在的错误和混淆,提高程序的安全性。

  • **内存管理一致:**从内存管理的角度来看,值传递机制与 Java 的内存模型相匹配。无论是基本数据类型的值还是引用数据类型的引用,都是在栈内存中进行传递和操作的,而对象本身存储在堆内存中。这种清晰的内存划分有助于提高垃圾回收的效率和准确性,也使得 Java 程序在内存管理方面更加稳定和可靠


34、java常见语法糖

  • 泛型
  • 自动装箱和自动拆箱
  • 增强for循环
  • 可变参数
  • 枚举
  • Lambda 表达式

35、java三大特性

  • 封装性:
    • **定义:**将类的某些信息隐藏在内部,不允许外部直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。
    • **实现方式:**通过四种权限修饰符,public,protected、private、缺省,来控制类、变量和方法的可见性。
    • **优点:**提高代码的安全性,不允许外部随意修改内部数据而导致错误。符合开闭原则(对扩展开放,对修改关闭)
  • 继承:
    • **定义:**继承是子类继承父类的属性和方法,子类可以在不修改父类的情况下,对继承的属性和方法进行扩展和重写。
    • **实现方式:**Java中通过extends关键字实现继承
    • 优点:
      • 提高代码的复用性,子类可以服用父类的代码
      • 类之间的层次更加分明,有利于代码的维护
  • 多态:
    • **定义:**多态是指同一个操作作用于不同的对象可以有不同的表现形式,Java中主要的表现形式为编译时多态(方法重载)和运行时多态(方法重写)
    • **实现方式:**泛型,子类的引用指向父类的对象等。
    • **优点:**提高代码的灵活性和可维护性

36、抽象类和接口的区别

  • 抽象类使用的是abstract关键字定义,而接口使用interface进行定义
  • 抽象类中可以包含抽象方法和普通方法,而接口中的方法默认都是抽象方法,在jdk8之后可以包含默认方法和静态方法(有方法体)
  • 抽象类可以包含各种成员变量,包括实例变量和静态变量,有不同的访问修饰符,而接口中的成员变量默认都是public static final类型的
  • 一个类只能继承一个抽象类,而一个类可以实现多个接口。
  • 抽象类主要用于对事务的抽象,可以提供部分实现,体现的是is a的关系。而接口时定义一种行为规范,它不提供任何实现,体现的是一种can do的关系

37、权限修饰符

  • public:任意位置可见
  • private:本类中可见
  • protected:本包以及子类中可见
  • 缺省:本包中可见

38、@autowired与@Resource

  • @Autowired:先根据类型进行匹配注入,后根据@Qualifier指定的名称进行注入
  • @Resource:先跟据名称进行注入,后根据类型进行匹配

39、Redis基本数据类型

字符串(String)、哈希(hash)、列表(List)、集合(Set)、有序集合(Sorted Set)

40、Redis缓存一致性

  • **设置过期时间:**可以为不同的数据类型固定过期时间,当时间过期时,从数据库中重新加载数据,确保数据的一致性
  • 在数据库更新数据时,先更新数据库,后更新缓存,并为数据更新添加事务,保证数据的一致性
  • 异步队列,将数据的写操作放入消息队列中,由专门的线程获取队列更新数据。

41、Redis缓存雪崩

  • 问题:Redis 缓存雪崩是指在缓存系统中,大量的缓存数据在同一时间失效(过期),或者缓存服务器在短时间内出现大量故障,导致大量的请求直接到达数据库,使得数据库的负载瞬间剧增,甚至可能导致数据库服务器崩溃,从而影响整个系统的性能和可用性。
  • 解决:
    • 设置一定范围的随机的过期时间,如以60分钟为基础,在50 ~ 70 之间的随机失效时间
    • 使用Redis集群,将数据分片储存到多个节点上,当某个节点出现故障时,其他节点继续提供服务保证整体的可用性
    • 主从复制,将数据从主节点复制到多个从节点上,当主节点故障时,从节点升级为主节点,保证服务的连续性

42、为什么String是不可变的

  • 安全性:
    • 防止数据被篡改,当一个String作为参数传递时,如果是可变的,可能在调用者不知情时导致数据的的更改
    • 避免安全漏洞,防止恶意代码篡改敏感信息
  • 缓存优化:
    • 使用字符串常量池保证Stirng的不可变性,节省空间
  • 线程安全:
    • 并发操作的安全性,当多个线程修改同一个字符串时,不会出先一个线程修改,导致其他线程不一致的情况

43、String如何实现不可变的

  • final修饰类
  • 成员变量用private final修饰
  • String类中的所有方法都返回的是一个新的字符串对象,防止对原有的数据的修改

44、反射创建class对象的方法

  • Class.forName("com.example.Person")
  • 使用.class语法
  • 使用getClass()方法

45、异常的分类

编译时异常、运行时异常、错误

46、try - with - resources的异常捕获

当在 try 关键字后面的括号 () 中创建并初始化资源(这些资源需要实现 AutoCloseable 接口)时,在 try 块执行结束后,无论是否抛出异常,这些资源都会被自动关闭。

47、java8新特性

  • Lambda 表达式
  • 函数式接口
  • 方法引用
  • Stream AIP
  • 接口的默认方法和静态方法

48、switch可用的数据类型

  • Java 8 之前,只能用于byte、short、int、char,在Java 7开始支持字符串以及对应的包装类
  • 从 Java 14 开始,支持包装类等类型

49、枚举类

枚举类是一种特殊的类,用于表示一组有限的常量

Java 中可以用 enum来定义枚举类

枚举类的表达清晰,提高代码的可读性

50、为什么重写equals和hashcode

  • equals 方法用于判断两个对象是否,相等,如果不重写equals方法,则会比较两个对象的引用,只有指向同一个地址才会返回true

  • hashCode 方法用于为对象生成一个 hash 值,在集合类(HashMap)中,用于快速定位存储对象的位置

    如果不重写,就可能导致相同对象在集合中被重复储存无法从集合中正确的检索到。

51、jvm内存区域有哪些

  • 线程私有区域:

    • 程序计数器,当前线程执行字节码的行号指示器
    • 虚拟机栈,用于存放方法的局部变量表等信息
    • 本地方法栈
  • 线程共享区域:

    • 堆,用于储存对象实体和数组,可以在物理内存上不连续,逻辑内存上连续

    • 方法区,用于储存类信息,常量,静态变量,即时编译器编译后的代码,jdk8后被元空间代替

      元空间不再与堆内存相连避免永久代的内存溢出问题,更好的管理方法区的内存

52、垃圾回收的算法有哪些

  • 标记—清除算法:

    • **过程:**先标记出所有可能需要回收的对象,在标记完成后同一回收所有标记的对象

    • 缺点:

      • **效率问题:**标记和清除两个过程的效率都不高

      • **空间问题:**会产生大量不连续的内存空间碎片,可能导致下一次分配较大的连续内存空间时,无法找到

        足够多的内存而不得不触发另一次的垃圾清除动作

  • 复制算法:

    • **过程:**将可能用到的内存按容量划分为大小相等的两块,每次只使用其中的一块,当这一块内存用完时,

      将还存活着的对象复制到另一块上面,然后再把使用过的内存空间一次清理掉。

    • **优点:**实现简单,运行效率高,不会产生内存碎片

    • **缺点:**将内存缩小到原来的一半,代价较高

  • 标记—整理算法:

    • 过程:根据对象存活周期的不同将内存划分为几块,一般 Java 把堆内存划分为新生代和老年代,在新生代中

      每次垃圾收集时都发现有大批对象死去,少量存活,那就选用复制算法,而老年代存活率高,没有额外空间对它进行分配担保,

      就必须用标记–清理或标记–整理算法

53、gc垃圾回收器有哪些

  • Serial 收集器
  • Serial Old 收集器
  • CMS 收集器
  • G1 收集器

54、io与nio的不同之处

  • 面向流与面向缓冲区
    • IO 是面向流的,意味着每次从流中读取一个或多个字节,如果需要再读取已读取的字节,只能重新从新的流中的开始位置读取
    • NIO 是面向缓冲区的,先读取数据到缓冲区,如果需要反复读取可以在缓冲区中前后移动位置进行处理
  • 阻塞与非阻塞
    • IO 流是阻塞的,当一个线程调用read()或write()操作时,该线程被阻塞,进入等待状态,无法进行其他任务
    • NIO 流是非阻塞的,当没有数据可读取时,线程不会阻塞,而是做其他的事情,稍后回来检查是否有数据可读取
  • NIO 的选择器
    • 一个选择器可以同时管理多个通道的事件,使得一个线程可以处理大量的连接

55、Java的类加载机制

  • **加载:**在内存中生成一个代表这个类的对象

  • 验证: 确保类的字节码符合JVM的规范和安全要求。

  • **准备:**为类变量(static修饰)分配内存并设置初始值

  • **解析:**将类中的符号引用转化为直接引用

  • **初始化:**执行类的初始化代码

  • Java的类加载机制采用了双亲委派模型,即,当一个类加载器收到类加载请求时,它首先会将请求委派给父类加载器完成

    只有当父类加载器无法完成加载请求时,子类加载器才会尝试自己加载,确保类的类的唯一性和安全性防止重复加载和恶意代码的篡改

56、详细说明双亲委派机制

双亲委派机制是 Java 类加载机制中的一种重要设计模式,主要用于确保类的唯一性和安全性。以下是对双亲委派机制的详细说明:

一、定义与工作原理

双亲委派机制规定,当一个类加载器收到类加载请求时,它不会自己去尝试加载这个类,而是把请求委派给父类加载器去完成。如果父类加载器无法加载这个类,子加载器才会尝试自己去加载。这个过程会一直向上委托,直到顶层的启动类加载器。如果启动类加载器也无法加载这个类,再依次向下由子加载器进行尝试加载。

例如,当应用程序类加载器(Application ClassLoader)收到一个加载类 com.example.MyClass 的请求时,它不会立即去加载这个类,而是把请求委派给它的父类加载器——扩展类加载器(Extension ClassLoader)。如果扩展类加载器也无法加载这个类,再继续向上委托给启动类加载器(Bootstrap ClassLoader)。如果启动类加载器仍然无法加载这个类,才会依次向下由扩展类加载器和应用程序类加载器尝试加载。

二、作用

  1. 确保类的唯一性:
  • 通过双亲委派机制,同一个类在 JVM 中只会被加载一次。因为类的加载请求会一直向上委托,最终由顶层的启动类加载器首先尝试加载。如果启动类加载器能够加载这个类,那么就会使用这个加载器加载的类,保证了类的唯一性。
  • 例如,在不同的应用程序中可能都有一个名为 java.util.ArrayList 的类,如果没有双亲委派机制,每个应用程序可能会使用自己的类加载器加载这个类,导致出现多个不同版本的 ArrayList 类,这会引起程序的混乱。
  1. 保证安全性:
  • 双亲委派机制可以防止恶意代码替换核心类库中的类。由于启动类加载器通常是由 JVM 自身实现的,它加载的是核心类库中的类,这些类具有较高的安全性和稳定性。
  • 如果没有双亲委派机制,恶意代码可以通过自定义的类加载器加载一个与核心类库中同名的类,并替换其中的方法,从而对系统造成安全威胁。有了双亲委派机制,当加载核心类库中的类时,会优先由启动类加载器进行加载,确保了核心类库的安全性。

三、实现方式

在 Java 中,双亲委派机制主要是通过 ClassLoader 类的 loadClass() 方法实现的。这个方法的默认实现会首先检查父类加载器是否已经加载了这个类,如果没有,则调用父类加载器的 loadClass() 方法进行加载。如果父类加载器无法加载这个类,才会调用当前类加载器的 findClass() 方法尝试自己去加载。

以下是一个简单的示例代码,展示了类加载器的层次结构和双亲委派机制的实现:

public class ClassLoaderExample {
    public static void main(String[] args) throws ClassNotFoundException {
        // 获取应用程序类加载器
        ClassLoader appClassLoader = ClassLoaderExample.class.getClassLoader();
        System.out.println("Application ClassLoader: " + appClassLoader);    
        // 获取扩展类加载器
        ClassLoader extClassLoader = appClassLoader.getParent();
        System.out.println("Extension ClassLoader: " + extClassLoader);

        // 获取启动类加载器
        ClassLoader bootstrapClassLoader = extClassLoader.getParent();
        System.out.println("Bootstrap ClassLoader: " + bootstrapClassLoader);

        // 加载一个类,触发双亲委派机制
        Class<?> clazz = Class.forName("java.lang.String");
        System.out.println("Loaded class: " + clazz.getClassLoader());
	}
}

在这个示例中,我们首先获取了应用程序类加载器、扩展类加载器和启动类加载器,并打印它们的信息。然后,我们使用 Class.forName() 方法加载 java.lang.String 类,这个过程会触发双亲委派机制,最终由启动类加载器加载这个类。

总之,双亲委派机制是 Java 类加载机制中的一个重要设计模式,它确保了类的唯一性和安全性,是 Java 语言安全稳定运行的重要保障。

57、tomcat是如何打破双亲委派机制的

  • 打破双亲委派机制的方法是通过重写类加载方法,先通过自己加载,如果加载不了,在委派给父类加载
  • Tomcat 通过重写类加载方法和打破双亲委派机制,实现了在一个服务器中部署多个 Web 应用程序时,各个应用程序之间类的隔离、独立加载、热部署和热加载等功能。
立创开源Link Hub多功能USB扩展坞:CH339F主控+4层板设计,实测网口/存储性能 本文深度评测了立创开源Link Hub多功能USB扩展坞,其采用CH339F主控芯片与4层PCB板设计,并严格进行阻抗匹配。实测表明,该扩展坞的USB接口与microSD读卡器性能均接近USB 2.0理论极限,百兆以太网口转换效率高,性能损失极小。设计上注重电源保护与信号完整性,是一个兼顾稳定性与成本的高完成度开源硬件项目。 阅读详情

相关推荐

告别环境依赖!用PyInstaller把PaddleOCR项目打包成独立EXE(附完整spec文件配置)

本文详细介绍了如何使用PyInstaller将PaddleOCR项目打包成独立EXE文件,彻底解决Python环境依赖问题。通过完整的spec文件配置和实战技巧,开发者可以轻松创建开箱即用的OCR工具,特别适合需要交付给非技术用户的场景。文章涵盖环境配置、模型打包、性能优化等关键环节,并提供了解决常见问题的方案。

weixin_33712987的博客 573

八股文01:基础篇

一共有8种:boolean 1 bit,不到一个字节byte 8 bit,1字节short 16 bit,2字节char 16 bit,2字节int 32 bit,4字节float 32 bit,4字节long 64 bit,8字节double 64 bit,8字节说明:1、int是基本数据类型,Integer是包装类型。int的默认值为0,Integer的默认值为null,因此Integer能区分出null和0。

ybq19513345431的博客 807

FPGA实战:AXI BRAM Controller写时序避坑指南(附Vivado配置步骤)

本文深入探讨了FPGA开发中AXI BRAM Controller的写时序实战要点与常见陷阱。文章聚焦于写地址与写数据通道的握手机制,详细解析了AWREADY、WVALID等关键信号的处理,并提供了Vivado中流水线深度、ECC等关键参数的配置步骤与优化建议,旨在帮助开发者有效规避时序问题,提升系统性能。

weixin_32306683的博客 170

JAVA 面试背 通过_java面试题背不下来怎么办?java面试题总结

Language》一书的附录中给出了一个Java关键字列表,其中有goto和const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉C语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字)。最近有很多java人员反映,说java面试题太多根本就背不下来,这可急坏了他们,毕竟要去面试java工作的,那么接下来,我们就来给大家讲解一下java面试题背不下来的解决方法。可以正确编译,因为s1+= 1;

m0_74825409的博客 1413

Android P HAL层添加HIDL实例(详细实现步骤)

Android P HAL层添加HIDL实例 本文将介绍如何在P OS上添加HIDL实例,简单增加seLinux策略使得可以在system_service调用测试,并用模拟器emulator验证。 调用过程为 APP->TestManager->TestService->ITast.hal 文章目录Android P HAL层添加HIDL实例实现过程一 、hardware部分1...

sinat_18179367的博客 1万+

STM32CubeMX——循迹传感器TCRT5000的使用

前言 人生如逆旅,我亦是行人。 ————苏轼《临江仙·送钱穆父》 一、介绍 TCRT5000描述:(带有晶体管输出的反射光学传感器) TCRT5000是一种反射式光学传感器,它包括一个红外发射器和一个3.5mm引线封装的光电晶体管,可阻挡可见光。还具有1mA 典型被测输出电流,2.5mm峰值工作距离,可应用传感与仪表,工业等行业。 TCRT5000具有紧凑的结构,其中发射光源和探测器布置在同一方向,通过使用来自物体的反射红外光束来感知物体的存在。工作波长为950毫米,探测器由光电晶体管组成

W_Oilpicture的博客 1万+

Java面试题

Java面试题(01)Java面试题(02)Java面试题(03)Java面试题(04)Java面试题(05)Java面试题(06)Java面试题(07)Java面试题(08)Java面试题(09)Java面试题(10)Java面试题(11)Java面试题(12)Java面试...

心底善良小剥皮de博客 4319

汇川EASY系列之以太网通讯(MODBUS_TCP做从站)

汇川easy系列PLC做MODBUS_TCP从站,,ModbusTCP服务器默认开启,无需设置通信协议(即不需要配置),端口号为“502”。ModbusTCP从站最多支持31个ModbusTCP客户端(ModbusTCP主站)同时连接。

这是一个长期关注工控行业技术的博客,实现0-1的突破,期待您的关注和留言 8871

java 入门面试题

基础:JDK 和 JRE 的区别== 和 equals 的区别基本类型和包装类对象使用 == 和 equals进行比较的结果?什么是装箱?什么是拆箱?装箱和拆箱的执行过程?常见问题?hashCode()相同,equals() 也一定为 true吗?final 在 java 中的作用final finally finalize()区别finally语句块一定执行吗?final 与 static 的区别return 与 finally 的执行顺序对返回值的影响String对象中的replace和replaceA

m0_74824755的博客 1167

Ambari 安装部署教程(手把手教学)【超级详细】

本文为读者提供了一套超详细的 Apache Ambari 安装部署教程,采用手把手教学方式,适合初学者及大数据运维人员。内容涵盖前期准备、环境配置、Ambari Server 与 Agent 安装、集群初始化配置、常见问题排查等全流程操作,确保用户能够顺利搭建稳定的 Hadoop 大数据平台管理系统。

Five的博客 1万+

高效计算斐波那契数列的C++实现及源码

斐波那契数列是一个非常经典的数学问题,通常递归方式计算斐波那契数列的时候会有很大的时间复杂度问题。首先,我们需要了解斐波那契数列的定义:斐波那契数列是指前两个数都为1,从第三个开始每个数都等于它前面两个数之和。因此,斐波那契数列的前几项为:1、1、2、3、5、8、13、21……在这个代码中,我们首先判断n是否特殊情况(即n等于0、1、2),然后通过循环计算得出对应的斐波那契数列值。通过这个例子,我们可以发现使用C++语言实现高效斐波那契数列计算的代码简单、易懂,并且时间复杂度相比递归方式有了很大的提升。

TechInk的博客 547

Java面试题(最新最全Java面试题汇总)

Java面试题(最新最全Java面试题汇总)JAVA相关基础知识Java面试题集-Java面试题,J2EE面试题集J2EE面试题集(附答案)Java常见面试题集--面试题全面综合(一)Java常见面试题集--面试题全面综合(二)Java面试题集(欢迎大家踊跃提供) 最全的C/C++面试题集(C/C++试题和部分答案)最全的C/C++面试题集(最全的C/C++试题集和答案)(续)一道有趣的C#考试题

首席技术执行官CTO(Chief Technology Officer)|技术总监--邓斌博客 3024

YOLO骨干网络改进-第1篇:深度解析YOLOv8的C2f模块原理与实现

首先,需要将自定义的C2f模块注册到Ultralytics的模块字典中。# 注册自定义模块"""自定义的C2f模块。"""# 自定义YOLOv8s配置文件:yolov8s_custom.yamlscales:# Backbonebackbone:# Headhead:# 加载自定义模型# 训练模型imgsz=640,batch=16,device=0,workers=8,设计理念:C2f模块是C3模块的演进,通过增加梯度分支来丰富梯度流,提升特征表示能力。结构原理。

2201_76125393的博客 110

2020最新Java面试题

@TOC1、面试题模块汇总 面试题包括以下十九个模块:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql、Redis、JVM 。如下图所示: 可能对于初学者不需要后面的框架和 ...

java开发郭靖 3053

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

最新Java面试题,常见面试题及答案汇总

Java最新常见面试题 + 答案汇总 原文地址:https://blog.youkuaiyun.com/sufu1065/article/details/88051083 1、面试题模块汇总 面试题包括以下十九个模块: Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate...

JustDI0209的博客 568

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Java经典面试题

这份面试题,包含的内容了十九个模块:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql、Redis、JVM。下面一起来看 208 道面试题,具体的内容。以下是网上整理的非常全面的面试题,当然,绝大多数人不可能全部用到,但是都罗列在此,大家可根据自己的情况,选择对应的模块进行阅读。

2401_87878486的博客 1339

【面试题】-java面试题总目录

前言:先吐槽一下面试吧,相信不少人都有这样的经历,其实你对某项技术已经掌握的很OK了,但在面试的时候却未必能发挥到很好,让面试官觉得你确实已经很好的掌握该技术,也就是说你实际对该技术掌握的程度有90%,但面试时表现出来的却只有30%甚至更少,这可能是表达能力的问题,但也可能很大程度是因为你没有刷面试题,有些平时几乎很少会用到地方没有涉及到刚好被问到了.就好生活中有些人开车开得很好,甚至是一些开车多...

老汉健身的博客 578

java面试题_2019 最新 200 道 Java 面试题

2015 年,因为工作岗位的变动,开始负责给集团招聘一些技术人员,出于对公司的负责,也为了更好的胜任技术经理的职位,在面试的这件事上,我做了大量的“功课”,首先我研究了几乎所有大厂的面试题,还和负责招聘工作的几个朋友,详细的探讨了 Java 面试所要涉及的知识点,于是就有了今天大家看到的这 200 多道面试题。为什么要公开这些面试题?原因一:身边从事 Java 开发的人员越来越多,我的表...

weixin_39734458的博客 154

Java面试题集锦

 Java面试题集锦 2017-09-26 阿木侠 Java知音 Java知音 Java知音 微信号 Java_friends 功能介绍 致力打造一个有情怀的Java相关技能推送号 这是整理之后的面试题,本来都是已经发过的,后台不断有小伙伴留言想我去把这些集中到一块儿看着方便,最近一直挺忙就一直没动手,今天终于抽出空来整理了,顺手把推荐书籍

java_2017_csdn的博客 3450

常用Java面试题

        以下链接都是一些洋人整理的常用Java面试题,有些答案很简单,需要读者在深度发掘,有的答案则很详细。我觉得想从事Java领域的人应该认真学习一下,另外企业的招聘人员也可以参考里面的相关题目。        http://www.roseindia.net/interviewquestions/corejava.shtml        http://java.sys-con.com

moneyice的专栏 3万+

大厂JAVA面试题

精心整理的近几年国内大厂的一些java面试题,希望对大家有所帮助

狗剩没有饭吃 1400

java面试题背不下来怎么办?java面试题总结

Language》一书的附录中给出了一个Java关键字列表,其中有goto和const,但是这两个是目前无法使用的关键字,因此有些地方将其称之为保留字,其实保留字这个词应该有更广泛的意义,因为熟悉C语言的程序员都知道,在系统类库中使用过的有特殊意义的单词或单词的组合都被视为保留字)。最近有很多java人员反映,说java面试题太多根本就背不下来,这可急坏了他们,毕竟要去面试java工作的,那么接下来,我们就来给大家讲解一下java面试题背不下来的解决方法。可以正确编译,因为s1+=1;...

m0_67401270的博客 1110

java面试题总结汇总

java面试题总结汇总 Java面试总结汇总,持续更新中… 序号 内容

更阑一霎的博客 747
上一篇: docker浅学
下一篇: 我的生活记(dz-cn)
o独酌o
博客等级 码龄3年 324粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值