java基础-JavaSE

41 阅读10分钟

前言

共24题。

JDK和JRE的区别是什么?

JDKJava开发工具包,JREJava运行时环境,二者的区别在于JREJava程序运行所必须的,包含jvmJava虚拟机)和一些Java的基础类库;JDKJava程序开发所必须的,它包含JRE和一些开发工具。

&和&&的区别是什么?

  • &&&都是逻辑运算符,都可以实现取并的效果,即符号两边的表达式都为true,结果才是true。不一样的是&&有短路的功能,即当符号前面的表达式为false时,后面的表达式将不再执行,而&没有这个功能。
  • 另外,&还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&表示按位与操作。

final、finally、finalize的区别是什么?

  • final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、 修饰变量表示该变量是一个常量不能被重新赋值。
  • finally一般作用在try-catch代码块中,在处理异常的时候,无论程序是否出现异常,写在finally中的代码都会被执行,一般用来释放一些资源。
  • finalizeObject类的一个方法,它会在一个对象被垃圾回收的时候自动被垃圾回收器来调用。

String、StringBuffer、 StringBuilder 、StringJoiner的区别?

区别有以下几点:

  1. 可变性String是不可变对象,其它的都是可变对象;
  2. 线程安全StringStringBuffer是线程安全的,StringBuilderStringJoiner是线程不安全的;
  3. 效率StringBuilderStringJoiner效率最高,StringBuffer居中,String效率最低;
  4. 使用场景:少量字符串的操作使用String,大量字符串的频繁操作在多线程下使用StringBuffer,单线程下可以使用StringBuilderStringJoiner

使用=和new创建字符串的区别是什么?

两种方式都可以创建出字符串,但是在内存分配上却是不一样的:

  1. 等号方式JVM会在常量池中创建一个字符串对象;
  2. new方式JVM会先判断常量池中是否有此字符串,如果没有,就在常量池中创建一个,而且无论常量池中是否有,它都会在堆内存中重新创建一个。

float f=3.4是否正确?

不正确。

因为直接写出的字面量3.4double类型的,doublefloat属于向下转型,这种情况Java是不允许的,要赋值的话,要强制类型转换float f = (float)3.4,或者是在声明字面量3.4的时候,直接声明成float类型,即写成float f = 3.4F

重写和重载的区别是什么?

都是用于描述方法间的关系的,区别在于:

  • 重写是存在于子父类之间的,一般用在父类的方法无法满足子类需求时,子类重写方法来自定义方法功能。它要求子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型。
  • 重载是存在于同一个类中的,一般用在功能相似的方法需要接收不同的参数时,它要求多个方法具有相同的名字,但方法具有不同的参数列表。

this和super的应用场景是什么?

都是Java提供的关键字。

  • this代表的是当前对象,一般用于在一个方法中调用本对象的成员变量或其它方法;
  • supper代表是父类对象,一般在本对象和父对象出现成员名称冲突时,强行调用父对象的成员,也经常用于调用父类的构造方法。

throw和throws的区别是什么?

  • throws:用在方法的声明上,声明当前方法可能抛出的异常;
  • throw:写在方法里,真正的抛出一个异常,抛出自定义异常。创建对象自定义抛出异常。

应该使用什么数据类型来计算价格?

如果不是特别关心内存和性能的话,使用BigDecimal,否则使用预定义精度的double类型。

==与equals的区别?

  1. ==是一个运算符,equalsObject类的方法:
  2. 用于基本类型的变量比较时: ==比较的是值是否相等,equals不能直接用于基本数据类型的比较,需要转换为其对应的包装类型。
  3. 用于引用类型的比较时。==equals都是比较栈内存中的地址是否相等,但是通常会重写equals方法去实现对象内容的比较。此外,在比较Integer引用数据类型时,==存在【-128——127】的缓存区间,在此缓存区间内比较的是值,在此之外都是地址。

接口和抽象类的区别?

它们的共同点是:都不能实例化对象。

它们的不同点是:

  • 抽象类一般用于抽取子类中的共同方法和属性,接口一般用于指定实现类的规范;
  • 抽象类可以有构造方法和静态代码块,接口中都不能有;
  • 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

说出几个常见的异常?

Java中的异常分为运行时异常编译时异常两大类:

  • 运行时异常都是RuntimeException类及其子类异常,这类异常的特点是不强行要求程序员进行处理,常见的有:

    • NullPointerException:空指针异常,调用了未经初始化的对象或者是不存在的对象
    • IndexOutOfBoundsException:数组角标越界异常,常见于操作数组对象时发生
    • ClassCastException:数据类型转换异常
    • NoSuchMethodException:方法不存在异常
  • 非运行时异常,也叫编译异常,是Exception的子类但不是RuntimeException的子类,类型上都属于Exception类及其子类。它要求程序员在编写代码的过程中提供异常处理方案,否则编译不通过,常见的有:IOExceptionSQLException等。

Java反射有了解吗?

反射是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法,并且可以调用它的任意一个方法,它主要应用于大量的框架底层,比如Spring/Spring BootMyBatis等等。

浅拷贝和深拷贝的区别?

  • 浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享;
  • 深拷贝:深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。简而言之,深拷贝把要复制的对象所引用的对象都复制了一遍。

Java中都有哪些引用类型?

  • 强引用:发生gc的时候不会被回收;
  • 软引用:有用但不是必须的对象,在发生内存溢出之前会被回收;
  • 弱引用:有用但不是必须的对象,在下一次gc时会被回收;
  • 虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用途是在gc时返回一个通知。

请分别列举出String中的方法(至少5个)和Object中的方法(至少3个)?

  • String:切割、截取、长度、替换replace、替换全部replaceall
  • Object: equal方法、wait方法、hashcode方法、notify方法。

多态怎样实现?

  • 继承:子类对方法重写;
  • 接口:实现接口并覆盖接口中方法。
  • 多态实现的三个必要条件:继承关系、子类重写父类方法、父类引用指向子类对象

面向对象的特征?

面向对象的特征就是封装、继承和多态:

  • 封装:把数据和方法封装在一个类中,控制访问权限,只保留对外的接口;
  • 继承:创建子类继承父类的属性和方法,在此基础上扩展修改,也可以添加自己的;
  • 多态:方法的重写和重载。

请阐述Java对象的初始化过程?

  1. 初始化静态成员
  2. 执行静态代码块
  3. 初始化普通成员
  4. 执行普通代码块
  5. 执行构造方法
  6. 如果对象有父类,则在自身初始化前先初始化父类

在try的括号里面有return一个值,那在哪里执行finally里的代码?

设利用return语句从try语句块中退出。在方法返回前,finally子句的内容将被执行。如果finally子句中也有一个return语句,这个返回值将会覆盖原始的返回值。

现在有两个类,一个父类一个子类,父类有两个私有成员字段A、B,子类有两个私有成员字段C、D,现在创建一个“对象子类 对象 = new 子类()”,请问这个对象有几个属性?对象能够操作多少属性?

这个对象有4个属性,因为初始化子类时,会优先初始化父类,子类继承了父类成员。对象所有属性都不可以操作,因为都是私有的。

String的判空判null,掌握几种方法,直接说代码实现?

  1. 直接判空判null
  2. 使用StringUtils.isEmpty()(Apache Commons Lang)
  3. 使用 StringUtils.isBlank()(Apache Commons Lang)
  4. 使用 Optional(Java 8及以上)
// 1、直接判空判null
if (str == null || str.isEmpty()) {
}
// 2、StringUtils.isEmpty()(Apache Commons Lang)
if (StringUtils.isEmpty(str)) {
    // String 为 null 或为空
}
// 3、StringUtils.isBlank()(Apache Commons Lang)
if (StringUtils.isBlank(str)) {
    // String 为 null、空或仅包含空白字符(如空格、制表符等)
}
// 4、使用 Optional(Java 8 及以上)
if (Optional.ofNullable(str).orElse("").isEmpty()) {
    // String 为 null 或为空
}

Stream流的foreach可以根据某些条件在过程中跳出吗?

不可以。

如果需要根据条件提前终止流操作,可以使用 anyMatchallMatch

  • anyMatch 判断流中是否至少有一个元素满足给定的条件,只要有一个满足条件,返回true,结束循环;
  • allMatch 判断流中是所有元素满足给定的条件,只要有一个不满足,返回false,结束循环。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

boolean result = numbers.stream()
    .anyMatch(n -> {
        if (n > 3) {
            System.out.println("找到大于 3 的元素: " + n);
            return true; // 提前终止
        }
        System.out.println("处理元素: " + n);
        return false;
    });

System.out.println("结果: " + result);

现有一个长字符串,计算里面有多少个数字、字母(不区分大小写)、符号,如何实现?

这面试官真是有病,这种问题放机试里啊,口述怎么说?

遍历字符串,使用Character.isDigit(char)可判断字符是否为数字,通过Character.isLetter(ch)可判断字符是否为字母,其他情况就是符号。

public class CharacterCounter {
    public static void main(String[] args) {
        String input = "Hello, World! 123 #$%";

        int digitCount = 0; // 数字计数
        int letterCount = 0; // 字母计数
        int symbolCount = 0; // 符号计数

        // 遍历字符串中的每个字符
        for (char ch : input.toCharArray()) {
            if (Character.isDigit(ch)) {
                digitCount++; // 数字
            } else if (Character.isLetter(ch)) {
                letterCount++; // 字母
            } else {
                symbolCount++; // 符号
            }
        }

        // 输出结果
        System.out.println("数字数量: " + digitCount);
        System.out.println("字母数量: " + letterCount);
        System.out.println("符号数量: " + symbolCount);
    }
}

谈谈你对序列化和反序列化的理解?

把对象转换为字节序列的过程称为对象的序列化;把字节序列恢复为对象的过程称为对象的反序列化。

实践之中,通常会让类实现Serializable接口,并显示声明private static final long serialVersionUID,通常可以在idea配置自动生成。(目的是避免类结构变化导致的序列化兼容性问题)

我知道的应用场景主要有两个:

  1. 当需要将对象保存到文件、数据库或缓存(如redis)中时,必须序列化;
  2. 对象的深拷贝

此外,如果某些字段必须要序列化,可使用transient关键字修饰,如:private transient String password