1、Java 语言有哪些特点
Java 语言的特点有:
①、面向对象。主要是:封装,继承,多态。
②、平台无关性。一次编写,到处运行,因此采用 Java 语言编写的程序具有很好的可移植性。
③、支持多线程。C++ 语言没有内置的多线程机制,因此必须调用操作系统的 API 来完成多线程程序设计,而 Java 却提供了封装好的多线程支持;
④、支持 JIT 编译,也就是即时编译。它可以在程序运行时将字节码转换为机器码来提高程序的运行速度。
2、JVM、JDK 和 JRE 有什么区别?
JVM:Java 虚拟机,是 Java 实现跨平台的关键,不同的操作系统有不同的 JVM 实现。JVM 负责将 Java 字节码转换为特定平台的机器码并执行。
JRE:Java 运行时环境,包含了运行 Java 程序所必需的库,以及 JVM。
JDK:Java SDK,包括 JRE,编译器 javac等。简单来说,JDK 包含 JRE,JRE 包含 JVM。
3、什么是字节码?采用字节码的好处是什么?
字节码是 Java 程序经过编译后产生的 .class 文件。
Java 程序从源代码到运行需要经过三步:
编译:将源代码文件 .java 编译成 JVM 可以识别的字节码文件 .class。
解释:JVM 运行字节码文件,将字节码翻译成操作系统能识别的机器码。
运行:操作系统运行二进制的机器码。
4、Java 有哪些数据类型?
4.1 给Integer最大值+1,是什么结果?
当给 Integer.MAX_VALUE 加 1 时,会发生溢出,变成 Integer.MIN_VALUE。
5、自动类型转换、强制类型转换了解吗?
6、什么是自动拆箱/装箱?
Integer i = 10; //装箱
int n = i; //拆箱
7、&和&&有什么区别?
& 是 逻辑与,&&是短路与运算。&&之所以称为短路运算是因为,如果&&左边的表达式的值是 false,右边的表达式会直接短路掉,不会进行运算。
例如在验证用户登录时判定用户名不是 null 而且不是空字符串,应当写为username != null && !username.equals(“”),二者的顺序不能交换,更不能用 & 运算符,因为第一个条件如果不成立,根本不能进行字符串的 equals 比较,会抛出 NullPointerException 异常。
注意:逻辑或运算符(|)和短路或运算符(||)的差别也是类似。
8、用效率最高的方法计算 2 乘以 8?
位运算。
9、float 是怎么表示小数的?
符号位(Sign bit):1 位
指数部分(Exponent):10 位
尾数部分(Mantissa,或 Fraction):21 位
10、讲一下数据准确性高是怎么保证的?
在金融计算中,保证数据准确性有两种方案,一种使用 BigDecimal,一种将浮点数转换为整数 int 进行计算。
肯定不能使用 float 和 double 类型,它们无法避免浮点数运算中常见的精度问题,比如无法准确地表示 0.1。
在处理小额支付或计算时,通过转换为较小的货币单位(如分),不仅提高了运算速度,还保证了计算的准确性。
11、面向对象编程有哪些特性?
- 继承允许一个类继承现有类(父类或者基类)的属性和方法。以提高代码的复用性,建立类之间的层次关系。
- 封装是指将数据和操作数据的方法捆绑在一起,形成一个独立的对象(类的实例)。
- 多态允许不同类的对象对同一消息做出响应,但表现出不同的行为(即方法的多样性)。
12、重载和重写的区别?
如果一个类有多个名字相同但参数个数不同的方法,我们通常称这些方法为方法重载。
如果子类具有和父类一样的方法(参数、返回类型和方法名都相同,但方法体不同),我们称之为方法重写。
13、访问修饰符 public、private、protected、以及默认时的区别?
14、this 关键字有什么作用?
this 是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。
this 的用法在 Java 中大体可以分为 3 种:
-
普通的直接引用,this 相当于是指向当前对象本身。
-
形参与成员变量名字重名,用 this 来区分:
public Person(String name,int age){
this.name=name;
this.age=age;
}
- 引用本类的构造方法。
15、抽象类和接口有什么区别?
一个类只能继承一个抽象类,但一个类可以实现多个接口。抽象类符合 is-a 的关系,而接口更像是 has-a 的关系。
抽象类可以定义构造方法,接口主要用于定义一组方法规范,不可以定义构造方法。
15.1 继承和抽象的区别?
继承是一种允许子类继承父类属性和方法的机制。通过继承,子类可以重用父类的代码。
抽象是一种隐藏复杂性和只显示必要部分的技术。在面向对象编程中,抽象可以通过抽象类和接口实现。
15.2 抽象类和普通类的区别?
抽象类使用 abstract 关键字定义,不能被实例化,只能作为其他类的父类。普通类没有 abstract 关键字,可以直接实例化。
抽象类可以包含抽象方法和非抽象方法。抽象方法没有方法体,必须由子类实现。普通类只能包含非抽象方法。
16、static 关键字了解吗?
修饰变量:静态变量为类级别变量,所有实例共享同一份数据。
修饰方法:静态方法为类级别方法,与实例无关。
修饰代码块:在类加载时初始化一些数据,只执行一次。
修饰内部类:与外部类绑定但独立于外部类实例。
修饰导入:可以直接访问静态成员,无需通过类名引用。
17、final、finally、finalize 的区别?
①、final 是一个修饰符,可以修饰类、方法和变量。当 final 修饰一个类时,表明这个类不能被继承;当 final 修饰一个方法时,表明这个方法不能被重写;当 final 修饰一个变量时,表明这个变量是个常量,一旦赋值后,就不能再被修改了。
②、finally 是 Java 中异常处理的一部分,用来创建 try 块后面的 finally 块。无论 try 块中的代码是否抛出异常,finally 块中的代码总是会被执行。通常,finally 块被用来释放资源,如关闭文件、数据库连接等。
③、finalize 是 Object 类的一个方法,用于在垃圾回收器将对象从内存中清除出去之前做一些必要的清理工作。这个方法在垃圾回收器准备释放对象占用的内存之前被自动调用。我们不能显式地调用 finalize 方法,因为它总是由垃圾回收器在适当的时间自动调用。
19、==和 equals 的区别?
在 Java 中,== 操作符和 equals() 方法用于比较两个对象:
①、==:用于比较两个对象的引用,即它们是否指向同一个对象实例,适用于基本数据类型。
如果两个变量引用同一个对象实例,== 返回 true,否则返回 false。
对于基本数据类型(如 int, double, char 等),== 比较的是值是否相等。
②、equals() 方法:用于比较两个对象的内容是否相等。默认情况下 equals() 方法的行为与 == 相同,即比较对象引用。
20、为什么重写 equals 时必须重写 hashCode ⽅法?
因为基于哈希的集合类(如 HashMap)需要基于这一点来正确存储和查找对象。
具体地说,HashMap 通过对象的 hashCode 将其存储在不同的桶中,当查找对象时,它需要使用 key 的 hashCode 来确定对象在哪个桶中,然后再通过 equals() 方法找到对应的对象。
如果重写了 equals()方法而没有重写 hashCode()方法,那么被认为相等的对象可能会有不同的哈希码,从而导致无法在 HashMap 中正确处理这些对象。
20.1 为什么要有 hashCode 方法?
hashCode 方法主要用来获取对象的哈希码,哈希码是由对象的内存地址或者对象的属性计算出来的,它是⼀个 int 类型的整数,通常是不会重复的,因此可以用来作为键值对的键,以提高查询效率。
20.2 为什么两个对象有相同的 hashcode 值,它们也不⼀定相等?
为了解决哈希冲突的问题,哈希表在处理键时,不仅会比较键对象的哈希码,还会使用 equals 方法来检查键对象是否真正相等。如果两个对象的哈希码相同,但通过 equals 方法比较结果为 false,那么这两个对象就不被视为相等。
21、Java 是值传递,还是引用传递?
Java 是值传递,不是引用传递。当一个对象被作为参数传递到方法中时,参数的值就是该对象的引用。即该对象在堆中的地址。
22、说说深拷贝和浅拷贝的区别?
浅拷贝会创建一个新对象,但这个新对象的属性和原对象的属性完全相同。如果属性是基本数据类型,拷贝的是基本数据类型的值;如果属性是引用类型,拷贝的是引用地址,因此新旧对象共享同一个引用对象。
深拷贝也会创建一个新对象,但会递归地复制所有的引用对象,确保新对象和原对象完全独立。新对象与原对象的任何更改都不会相互影响。
23、Java 创建对象有哪几种方式?
Java 有四种创建对象的方式:
①、new 关键字创建,这是最常见和直接的方式,通过调用类的构造方法来创建对象。
②、反射机制创建,反射机制允许在运行时创建对象,并且可以访问类的私有成员,在框架和工具类中比较常见。
Class clazz = Class.forName("Person");
Person person = (Person) clazz.newInstance();
③、clone 拷贝创建,通过 clone 方法创建对象,需要实现 Cloneable 接口并重写 clone 方法。
④、序列化机制创建,通过序列化将对象转换为字节流,再通过反序列化从字节流中恢复对象。需要实现 Serializable 接口。
Person person = new Person();
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("person.txt"));
os.writeObject(person);
ObjectInputStream is = new ObjectInputStream(new FileInputStream("person.txt"));
Person person2 = (Person) is.readObject();
23.1 new 子类的时候,子类和父类静态代码块,构造方法的执行顺序?
- 首先执行父类的静态代码块(仅在类第一次加载时执行)。
- 接着执行子类的静态代码块(仅在类第一次加载时执行)。
- 再执行父类的构造方法。
- 最后执行子类的构造方法。
24、String 是 Java 基本数据类型吗?可以被继承吗?
不是,String 是一个类,属于引用数据类型。Java 的基本数据类型包括八种:四种整型(byte、short、int、long)、两种浮点型(float、double)、一种字符型(char)和一种布尔型(boolean)。
24.1 String 类可以继承吗?
不行。String 类使用 final 修饰,是所谓的不可变类,无法被继承。
24.2 String 有哪些常用方法?
- length() - 返回字符串的长度。
- charAt(int index) - 返回指定位置的字符。
- substring(int beginIndex, int endIndex) - 返回字符串的一个子串,从 beginIndex 到 endIndex-1。
- contains(CharSequence s) - 检查字符串是否包含指定的字符序列。
- equals(Object anotherObject) - 比较两个字符串的内容是否相等。
- indexOf(int ch) 和 indexOf(String str) - 返回指定字符或字符串首次出现的位置。
- replace(char oldChar, char newChar) 和 replace(CharSequence target, CharSequence replacement) - 替换字符串中的字符或字符序列。
- trim() - 去除字符串两端的空白字符。
- split(String regex) - 根据给定正则表达式的匹配拆分此字符串。
25、String 和 StringBuilder、StringBuffer 的区别?
String、StringBuilder 和 StringBuffer 在 Java 中都是用于处理字符串的,它们之间的区别是,String 是不可变的,平常开发用得最多,当遇到大量字符串连接时,就用 StringBuilder,它不会生成很多新的对象,StringBuffer 和 StringBuilder 类似,但每个方法上都加了 synchronized 关键字,所以是线程安全的。
26、String str2 = “abc” 和 new String(“abc”) 的区别?
直接使用双引号为字符串变量赋值时,Java 首先会检查字符串常量池中是否已经存在相同内容的字符串。
如果存在,Java 就会让新的变量引用池中的那个字符串;
如果不存在,它会创建一个新的字符串,放入池中,并让变量引用它。
使用 new String(“abc”) 的方式创建字符串时,实际分为两步:
第一步,先检查字符串字面量 “abc” 是否在字符串常量池中,如果没有则创建一个;如果已经存在,则引用它。
第二步,在堆中再创建一个新的字符串对象,并将其初始化为字符串常量池中 “abc” 的一个副本。
27、String 是不可变类吗?字符串拼接是如何实现的?
String 是不可变的,这意味着一旦一个 String 对象被创建,其存储的文本内容就不能被改变。这是因为:
①、不可变性使得 String 对象在使用中更加安全。因为字符串经常用作参数传递给其他 Java 方法,例如网络连接、打开文件等。
如果 String 是可变的,这些方法调用的参数值就可能在不知不觉中被改变,从而导致网络连接被篡改、文件被莫名其妙地修改等问题。
②、不可变的对象因为状态不会改变,所以更容易进行缓存和重用。字符串常量池的出现正是基于这个原因。当代码中出现相同的字符串字面量时,JVM 会确保所有的引用都指向常量池中的同一个对象,从而节约内存。
③、因为 String 的内容不会改变,所以它的哈希值也就固定不变。这使得 String 对象特别适合作为 HashMap 或 HashSet 等集合的键,因为计算哈希值只需要进行一次,提高了哈希表操作的效率。
因为 String 是不可变的,因此通过 + 操作符进行的字符串拼接,会生成新的字符串对象。
28、intern 方法有什么作用?
如果当前字符串内容存在于字符串常量池,直接返回字符串常量池中的字符串。否则,将此 String 对象添加到池中,并返回 String 对象的引用。