Java面试黄金宝典1

1. 8 种基本数据类型

  • 整数类型
    1. byte
      它是最小的整数类型,占用 1 个字节(8 位)。在一些对内存使用要求极高的场景,比如嵌入式系统开发、数据传输时对数据量有严格限制的情况,会使用 byte 类型。例如,在处理图像数据中的像素值时,如果每个像素值范围在 -128 到 127 之间,就可以用 byte 存储。
    2. short
      占用 2 个字节(16 位)。在一些特定的图形处理库中,可能会使用 short 来表示一些相对较小的坐标值或颜色分量值,因为它比 int 更节省内存。
    3. int
      这是 Java 中最常用的整数类型,占用 4 个字节(32 位)。在日常的编程中,如计数、索引、循环控制等场景,通常都会使用 int 类型。例如,遍历数组、计算循环次数等。
    4. long
      占用 8 个字节(64 位)。当需要处理非常大的整数时,如计算时间戳(以毫秒为单位)、处理大数据量的统计结果等,就需要使用 long 类型。定义时,需要在数字后面加上 Ll,建议使用大写的 L,因为小写的 l 容易与数字 1 混淆。
  • 浮点类型
    1. float
      单精度浮点数,占用 4 个字节(32 位)。在一些对精度要求不高的科学计算、图形处理中的一些近似计算等场景中使用。例如,在游戏开发中,计算物体的位置、速度等,可能只需要一定的精度,此时可以使用 float 类型。定义时需要在数字后面加上 Ff
    2. double
      双精度浮点数,占用 8 个字节(64 位)。是 Java 中默认的浮点类型,精度比 float 高。在大多数需要处理小数的场景中,如金融计算、科学研究等,都会使用 double 类型。
  • 字符类型
    1. char
      占用 2 个字节(16 位),基于 Unicode 字符集,可以表示世界上大多数语言的字符。在处理文本、字符串操作时,char 类型非常有用。例如,遍历字符串中的每个字符时,就会用到 char 类型。
  • 布尔类型
    1. boolean
      只有两个值,truefalse,用于逻辑判断。在条件语句(如 ifwhile 等)、逻辑运算中广泛使用。

2. 什么是装箱和拆箱

  • 装箱
    1. 自动装箱:Java 编译器会自动将基本数据类型转换为对应的包装类对象。例如:

java

复制代码
int num = 10;
Integer integerObj = num; // 自动装箱

2. 手动装箱 :在 Java 9 及以前,可以使用包装类的构造方法进行装箱;Java 9 及以后,部分构造方法已被弃用,建议使用 valueOf 方法。例如:

java

复制代码
int num = 10;
// Java 9 以前
// Integer integerObj2 = new Integer(num); 
// Java 9 及以后
Integer integerObj2 = Integer.valueOf(num); 

使用 valueOf 方法的好处是,它会缓存一些常用的值,提高性能。例如,Integer 类会缓存 -128 到 127 之间的整数对象,当使用 valueOf 方法创建这个范围内的对象时,会直接返回缓存的对象,而不是创建新的对象。

  • 拆箱
    1. 自动拆箱:Java 编译器会自动将包装类对象转换为对应的基本数据类型。例如:

java

复制代码
Integer integer = 20;
int num2 = integer; // 自动拆箱

2. 手动拆箱 :调用包装类的 xxxValue() 方法进行拆箱。例如:

java

复制代码
Integer integer = 20;
int num3 = integer.intValue(); // 手动拆箱

3. String 转出 int 型,判断能不能转?如何转?

  • 判断能否转换的更多方法
  1. 正则表达式:可以使用正则表达式判断字符串是否只包含数字字符。例如:

java

复制代码
import java.util.regex.Pattern;

public class StringToInt {
    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("^-?\\d+$");
        return pattern.matcher(str).matches();
    }

    public static void main(String[] args) {
        String str = "123";
        if (isNumeric(str)) {
            try {
                int num = Integer.parseInt(str);
                System.out.println(num);
            } catch (NumberFormatException e) {
                System.out.println("字符串不能转换为整数");
            }
        } else {
            System.out.println("字符串不是有效的数字");
        }
    }
}

2. 尝试转换并捕获异常 :直接尝试使用 Integer.parseInt()Integer.valueOf() 方法进行转换,并捕获 NumberFormatException 异常。例如:

java

复制代码
public class StringToInt2 {
    public static void main(String[] args) {
        String str = "abc";
        try {
            int num = Integer.parseInt(str);
            System.out.println(num);
        } catch (NumberFormatException e) {
            System.out.println("字符串不能转换为整数");
        }
    }
}
  • 转换方法的性能分析
  1. Integer.parseInt() 方法直接返回基本数据类型 int,效率相对较高,适用于需要直接使用 int 类型的场景。
  2. Integer.valueOf() 方法返回的是 Integer 对象,在需要基本数据类型时会自动拆箱。如果需要使用 Integer 对象,或者在泛型、集合等场景中使用,建议使用 Integer.valueOf() 方法。

4. short s1 = 1; s1 = s1 + 1; 有什么错?short s1 = 1; s1 +=1; 有什么错?

  • short s1 = 1; s1 = s1 + 1;
    在 Java 中,当进行算术运算时,shortbytechar 类型会自动提升为 int 类型。所以 s1 + 1 的结果是 int 类型。而 s1short 类型,将 int 类型的值赋给 short 类型的变量需要进行强制类型转换,否则会导致编译错误。正确的写法是:

java

复制代码
short s1 = 1;
s1 = (short) (s1 + 1);
  • short s1 = 1; s1 +=1;
    += 是复合赋值运算符,它会自动进行类型转换。s1 += 1 实际上等价于 s1 = (short)(s1 + 1),所以不会有编译错误。

5. Int 与 Integer 区别

  • 内存使用差异
  1. int 类型变量直接存储值,存储在栈内存中,占用的内存空间是固定的,根据类型不同而不同(如 int 占用 4 个字节)。
  2. Integer 是引用类型,变量存储的是对象的引用,对象本身存储在堆内存中,引用存储在栈内存中。除了对象本身占用的内存外,还需要额外的内存来存储引用。
  • 性能差异
  1. 在进行大量的数值计算时,int 类型的性能要高于 Integer 类型。因为 int 类型不需要进行装箱和拆箱操作,而 Integer 类型在进行计算时需要进行装箱和拆箱,会带来一定的性能开销。

6. 字节字符区别

  • 编码与解码
  1. 字节:字节是计算机存储和传输数据的基本单位,在不同的编码格式下,字节与字符的对应关系不同。例如,在 ASCII 编码中,一个字节对应一个字符;在 UTF - 8 编码中,一个字符可能由 1 到 4 个字节表示。
  2. 字符 :字符是人类能够识别的符号,在 Java 中,char 类型基于 Unicode 字符集。在进行文件读写、网络传输等操作时,需要进行字符编码和解码。例如,将字符串转换为字节数组时,需要指定编码格式:

java

复制代码
String str = "你好";
try {
    byte[] bytes = str.getBytes("UTF-8");
} catch (Exception e) {
    e.printStackTrace();
}
  • 处理场景
  1. 字节处理 :在处理二进制文件(如图片、视频、音频等)时,主要使用字节进行操作。例如,使用 FileInputStreamFileOutputStream 进行文件读写时,读取和写入的都是字节数据。
  2. 字符处理 :在处理文本文件(如 .txt 文件)、进行字符串操作时,主要使用字符进行操作。例如,使用 FileReaderFileWriter 进行文件读写时,读取和写入的都是字符数据。

7. 基本类型与引用类型的区别

  • 垃圾回收
  1. 基本类型:基本类型变量存储在栈内存中,当变量的作用域结束时,栈内存中的空间会自动释放,不需要垃圾回收机制进行处理。
  2. 引用类型:引用类型对象存储在堆内存中,当对象不再被引用时,会被垃圾回收机制标记为可回收对象,在合适的时机进行回收。
  • 数组与基本类型、引用类型的关系
  1. 基本类型数组:数组中的每个元素都是基本类型,数组本身是引用类型,存储在堆内存中,而数组元素存储在数组所占用的内存空间中。例如:

java

复制代码
int[] arr = new int[10];

2. 引用类型数组:数组中的每个元素都是引用类型,数组本身和数组元素都存储在堆内存中。例如:

java

复制代码
String[] strArr = new String[10];

8. 重写重载封装继承多态

  • 重写的注意事项
  1. 异常处理 :子类重写的方法不能抛出比父类被重写方法更多、更宽泛的异常。例如,如果父类方法抛出 IOException,子类重写的方法可以抛出 IOException 或其子类异常,或者不抛出异常。
  2. 方法签名严格匹配:方法名、参数列表和返回值类型必须与父类被重写的方法相同(子类返回值类型可以是父类返回值类型的子类,这称为协变返回类型)。
  • 重载的实现原理

重载方法是根据方法的参数列表(参数个数、类型或顺序)来区分的。在编译时,编译器会根据调用方法时传递的参数类型和数量,选择合适的重载方法进行调用。

  • 封装的优势
  1. 提高安全性 :通过将数据和操作数据的方法封装在一起,使用 private 访问修饰符隐藏对象的内部实现细节,只对外提供必要的接口,可以防止外部代码直接访问和修改对象的内部数据,从而提高代码的安全性。
  2. 提高可维护性:当需要修改对象的内部实现时,只需要修改封装类的内部代码,而不会影响到外部调用代码,降低了代码的耦合度,提高了代码的可维护性。
  • 继承的限制和拓展
  1. 单继承限制:Java 只支持单继承,即一个子类只能有一个直接父类。但可以通过实现多个接口来实现类似多继承的功能。
  2. 方法重写和调用父类方法 :子类可以重写父类的方法来实现自己的功能,同时可以使用 super 关键字调用父类的方法。例如:

java

复制代码
class Parent {
    public void print() {
        System.out.println("Parent");
    }
}

class Child extends Parent {
    @Override
    public void print() {
        super.print();
        System.out.println("Child");
    }
}
  • 多态的实现方式和应用场景
  1. 实现方式:多态的实现方式有继承和接口。通过父类引用指向子类对象,在运行时根据实际对象类型调用相应的方法。例如:

java

复制代码
class Animal {
    public void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.sound();
    }
}

2.应用场景:多态在代码的可扩展性和可维护性方面有很大的优势。例如,在游戏开发中,不同的角色可能有不同的攻击方式,可以通过多态来实现统一的攻击接口,根据实际角色类型调用相应的攻击方法。

9.是否可以覆盖 (override) 一个 private 或者是 static 的方法?

  • private 方法
    private 方法的作用域仅限于当前类,子类无法访问父类的 private 方法。所以子类中定义的与父类 private 方法同名的方法,只是一个新的方法,与父类的方法没有关系。例如:

java

复制代码
class Parent {
    private void privateMethod() {
        System.out.println("Parent private method");
    }
}

class Child extends Parent {
    public void privateMethod() {
        System.out.println("Child private method");
    }
}

在这个例子中,Child 类中的 privateMethod 方法与 Parent 类中的 privateMethod 方法没有重写关系。

  • static 方法
    静态方法属于类,而不是对象。子类可以定义与父类静态方法同名的静态方法,这称为方法隐藏。调用时,根据引用类型决定调用哪个方法,而不是根据实际对象类型。例如:

java

复制代码
class Parent {
    public static void staticMethod() {
        System.out.println("Parent static method");
    }
}

class Child extends Parent {
    public static void staticMethod() {
        System.out.println("Child static method");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent parent = new Child();
        parent.staticMethod(); // 调用 Parent 类的 staticMethod 方法
    }
}

10. 什么是 PriorityQueue

  • 实现原理

PriorityQueue 基于优先级堆实现,优先级堆是一种完全二叉树,它的每个节点的值都大于或等于其子节点的值(最大堆),或者小于或等于其子节点的值(最小堆)。在 PriorityQueue 中,默认是最小堆。插入和删除元素的时间复杂度为 O (log n),获取队首元素的时间复杂度为 O (1)。

  • 自定义比较器

可以通过提供自定义的 Comparator 来指定元素的排序规则。例如,要创建一个最大堆的 PriorityQueue

java

复制代码
import java.util.PriorityQueue;
import java.util.Comparator;

public class PriorityQueueExample {
    public static void main(String[] args) {
        PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());
        pq.add(3);
        pq.add(1);
        pq.add(2);

        while (!pq.isEmpty()) {
            System.out.println(pq.poll());
        }
    }
}
  • 应用场景拓展
  1. 任务调度 :在操作系统中,任务调度器可以使用 PriorityQueue 来管理任务,根据任务的优先级来决定任务的执行顺序。
  2. Dijkstra 算法 :在图算法中,Dijkstra 算法可以使用 PriorityQueue 来优化,提高算法的效率。

友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读

https://download.csdn.net/download/ylfhpy/90493708

相关推荐
genispan10 分钟前
python基础8 单元测试
开发语言·python·单元测试
WispX88817 分钟前
【JVM】GC 常见问题
java·jvm·算法
安忘2 小时前
LeetCode-274.H 指数
算法·leetcode·职场和发展
xxxmmc2 小时前
Leetcode 160 Intersection of Two Linked Lists
算法·leetcode·双指针
极客先躯2 小时前
高级java每日一道面试题-2025年3月05日-微服务篇[Eureka篇]-Eureka在微服务架构中的角色?
java·微服务·架构·服务注册·健康检查·架构服务发现
Y.O.U..3 小时前
美团AI面试总结
网络·面试·职场和发展
VincentStory3 小时前
分享一个项目中遇到的一个算法题
android·算法
北漂老男孩4 小时前
IntelliJ IDEA 调试技巧指南
java·ide·intellij-idea
钢铁男儿4 小时前
Python 生成数据(随机漫步)
开发语言·python·信息可视化
八股文领域大手子4 小时前
Leetcode32 最长有效括号深度解析
java·数据库·redis·sql·mysql