• Java基础面试题突击系列6


    👩🏻 作者:一只IT攻城狮 ,关注我不迷路
    ❤️《java面试核心知识》突击系列,持续更新…
    💐 面试必知必会学习路线:Java技术栈面试系列+SpringCloud项目实战学习路线
    📝再小的收获x365天都会成就不一样的自己,一起学习,一起进步。

    一、为什么重写equals方法必须要重写hashCode方法

    因为有强制的规范指定需要同时重写 hashcode 与 equal 是方法。

    如果只重写了equals方法而没有重写hashCode方法的话,则会违反约定,因为相等的对象必须具有相等的散列码(hashCode)。许多容器类,如 HashMap、HashSet 都依赖于此规定,比较对象相等首先要比较hashCode是否相等,如果hashCode相等才会去比较equals。

    二、Java泛型与泛型擦除

    Java泛型是J2 SE1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

    1、Java泛型好处:

    • 第一是泛化。可以用T代表任意类型Java语言中引入泛型是一个较大的功能增强不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了,这带来了很多好处。
    • 第二是类型安全。泛型的一个主要目标就是提高Java程序的类型安全,使用泛型可以使编译器知道变量的类型限制,进而可以在更高程度上验证类型假设。如果不用泛型,则必须使用强制类型转换,而强制类型转换不安全,在运行期可能发生ClassCast Exception异常,如果使用泛型,则会在编译期就能发现该错误。
    • 第三是消除强制类型转换。泛型可以消除源代码中的许多强制类型转换,这样可以使代码更加可读,并减少出错的机会。
    • 第四是向后兼容。支持泛型的Java编译器(例如JDK1.5中的Javac)可以用来编译经过泛型扩充的Java程序(Generics Java程序),但是现有的没有使用泛型扩充的Java程序仍然可以用这些编译器来编译。

    2、泛型擦除:

    泛型信息只存在于代码编译阶段,但是在java的运行期(已经生成字节码文件后)与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。
    Java 泛型擦除是 Java 泛型中的一个重要特性,其目的是避免过多的创建类而造成的运行时的过度消耗,及兼容问题。

    三、静态变量和实例变量的区别

    静态变量是被 static 修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;

    实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它。
    静态变量可以实现让多个对象共享内存。

    补充:在 Java 开发中,上下文类和工具类中通常会有大量的静态成员。

    四、什么是死锁?

    当线程 A 持有独占锁a,并尝试去获取独占锁 b 的同时,线程 B 持有独占锁 b,并尝试获取独占锁 a 的情况下,就会发生 AB 两个线程由于互相持有对方需要的锁,而发生的阻塞现象,我们称为死锁。

    五、线程的 sleep()方法和 yield()方法有什么区别?

    1、sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
    2、 线程执行 sleep()方法后转入阻塞(blocked)状态,而执行 yield()方法后转入就绪(ready)状态;
    3、 sleep()方法声明抛出 InterruptedException,而 yield()方法没有声明任何异常;
    4、 sleep()方法比 yield()方法(跟操作系统 CPU 调度相关)具有更好的可移植性。

    六、事务的 ACID 是指什么?

    1、原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作
    的失败都会导致整个事务的失败;
    2、一致性(Consistent):事务结束后系统状态是一致的;
    3、隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
    4、持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难
    性的失败。通过日志和同步备份可以在故障发生后重建数据。

    七、什么是线程局部变量?

    线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共享。

    Java 提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务器)使用线程局部变量的时候要特别小心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风险。

    八、JDBC 操作数据库的步骤

    1、加载驱动。

    Class.forName("oracle.jdbc.driver.OracleDriver"); 
    
    • 1

    2、创建连接。

    Connection con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger"); 
    
    • 1

    3、创建语句。

    PreparedStatement ps = con.prepareStatement("select * from emp where sal between ? and ?"); 
    ps.setInt(1, 1000); 
    ps.setInt(2, 3000); 
    
    • 1
    • 2
    • 3

    4、执行语句。

    ResultSet rs = ps.executeQuery();
    
    • 1

    5、处理结果。

    while(rs.next()) { 
    System.out.println(rs.getInt("empno") + " - " + 
    rs.getString("ename")); 
    } 
    
    • 1
    • 2
    • 3
    • 4

    6、关闭资源。

    finally { 
    if(con != null) { 
    try { 
    con.close(); 
    } catch (SQLException e) { 
    e.printStackTrace(); 
    } 
    } 
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    提示:关闭外部资源的顺序应该和打开的顺序相反,也就是说先关闭 ResultSet、 再关闭 Statement、在关闭Connection。上面的代码只关闭了 Connection(连接),虽然通常情况下在关闭连接时,连接上创建的语句和打开的游标也会关闭,但不能保证总是如此,因此应该按照刚才说的顺序分别关闭。此外,第一步加载驱动在 JDBC 4.0 中是可以省略的(自动从类路径中加载驱动),但是我们建议保留。

    九、怎么确保一个集合不能被修改?

    可以使用 Collections. unmodifiableCollection(Collection c) 方法来创建一个只读集合,这样改变集合的任何操作都会抛出 Java. lang. UnsupportedOperationException 异常。
    示例代码如下:

    List<String> list = new ArrayList<>(); 
    list. add("x"); 
    Collection<String> clist = Collections. unmodifiableCollection(list); 
    clist. add("y"); // 运行时此行报错 
    System. out. println(list. size()); 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    十、Statement 和 PreparedStatement 有什么区别?哪个性能更好?

    与 Statement 相比,
    1、PreparedStatement 接口代表预编译的语句,它主要的优势在于可以减少 SQL 的编译错误并增加 SQL 的安全性(减少 SQL 注射攻击的可能性);
    2、PreparedStatement 中的 SQL 语句是可以带参数的,避免了用字符串连接拼接 SQL 语句的麻烦和不安全;
    3、当批量处理 SQL 或频繁执行相同的查询时,PreparedStatement 有明显的性能上的优势,由于数据库可以将编译优化后的 SQL 语句缓存起来,下次执行相同结构的语句时就会很快(不用再次编译和生成执行计划)。

    补充:为了提供对存储过程的调用,JDBC API 中还提供了 CallableStatement 接口。存储过程(Stored Procedure)是数据库中一组为了完成特定功能的 SQL 语句的集合,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。虽然调用存储过程会在网络开销、安全 性、性能上获得很多好处,但是存在如果底层数据库发生迁移时就会有很多麻烦, 因为每种数据库的存储过程在书写上存在不少的差别。

    十一、用哪两种方式来实现集合的排序?

    你可以使用有序集合,如 TreeSet 或 TreeMap,你也可以使用有顺序的的集合,如 list,然后通过Collections.sort() 来排序。

    十二、poll() 方法和 remove() 方法的区别?

    poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。

    十三、Java 中的 LinkedList 是单向链表还是双向链表?

    是双向链表

    十四、Java 中的 TreeMap 是采用什么实现的?

    Java 中的 TreeMap 是使用红黑树实现的。

    十五、Java 中Comparator 与 Comparable 有什么不同?

    Comparable 接口用于定义对象的自然顺序,而 comparator 通常用于定义用户定制的顺序。Comparable 总是只有一个,但是可以有多个 comparator 来定义对象的顺序。

    在这里插入图片描述

  • 相关阅读:
    Docker开启远程访问+idea配置docker+dockerfile发布java项目
    5.7w字?GitHub标星120K的Java面试知识点总结,真就物超所值了
    分析A股交易接口获取股票信息的整个过程
    Linux知识点 -- 网络基础(二)-- 应用层
    从0开始学汇编第一天:基础知识
    在vue-cli脚手架项目中使用bootstrap框架和jquery
    深入了解 RabbitMQ:高性能消息中间件
    MySQL数据库管理基操作
    Scanner之nextInt()方法的使用
    上周热点回顾(2.14-2.20)
  • 原文地址:https://blog.csdn.net/weixin_47061482/article/details/130888820