Java常见面试题(day10)

  1. 在接口的定义中,不应该带括号,如interfaceB(){void print();}是错误的,正确的应该是interface B{stastic void print();} 接口默认是抽象的,不需要使用abstract关键字;接口的方法中不能有实现,如interface B {voidprint(){}};中 voidprint()后不能有{}的内容;一个类可以实现多个接口,如class MyClass implements Interface1, Interface2 {}

    抽象类和接口都是为了把实际事物抽象化。不同在于,接口抽象出来的都是接口方法,不管实现。抽象类抽出来的既有属性,也有方法,既有需要子类自己实现的抽象方法,也有已经实现好的方法供子类继承使用。抽象的东西不能实例;抽象类可以实现接口

  2. abstract修饰类会使类成为抽象类,这个类将不能生成对象实例,但可以做为对象变量声明的类型,也就是编译时类型,抽象类就像当于一类的半成品,需要子类继承并覆盖其中的抽象方法。abstract修饰方法,会使这个方法变成抽象方法,也就是只有声明(定义)而没有实现,实现部分以";"代替。需要子类继承实现(覆盖)。有抽象方法的类一定是抽象类,但抽象类中的不一定都是抽象方法。 abstract修饰方法就是要求其子类覆盖(实现)这个方法。调用时可以以多态方式调用子类覆盖(实现)后的方法,也就是说抽象方法必须在其子类中实现,除非子类本身也是抽象类。 注意:父类是抽象类,其中有抽象方法,那么子类继承父类,并把父类中的所有抽象方法都实现(覆盖)了,子类才有创建对象的实例的能力,否则子类也必须是抽象类。抽象类中可以有构造方法,是子类在构造子类对象时需要调用的父类(抽象类)的构造方法。

  3. 当一个线程调用 sleep() 方法时,该线程会进入“阻塞状态(Blocked State)”或“休眠状态(Sleeping State)”。在这段时间内,线程不会占用CPU资源,直到指定的睡眠时间到期或被中断。此时,线程会从阻塞状态回到可运行状态(Runnable State),等待CPU的调度重新运行。

  4. 在类的定义中可以有两个或多个同名函数,这种现象称为方法重载(Method Overloading)。

    方法重载指在同一个类中定义多个同名的方法,但这些方法的参数列表(参数的个数、类型或顺序)必须不同。通过方法重载,可以在一个类中定义多个实现不同功能的同名方法。

    class Example {
        void display() {
            System.out.println("No arguments");
        }
    ​
        void display(int a) {
            System.out.println("One integer argument: " + a);
        }
    ​
        void display(String a) {
            System.out.println("One string argument: " + a);
        }
    }
    在上面的例子中,类 Example 中定义了三个同名方法 display,它们的参数列表各不相同,这就是方法重载。

  5. try-catch 是 Java 和许多其他编程语言中用于异常处理的关键字组合,它允许程序员优雅地捕获和处理运行时可能出现的错误。

    try 块:包裹可能会抛出异常的代码。当 try 块中的代码执行时,如果出现了异常(例如除数为零、文件未找到等),控制权将立即转到相应的 catch 块。

    catch 块:每一个 catch 块都与一个或一类异常类型相关联。当 try 块中的代码抛出与 catch 块声明的异常类型相匹配的异常时,与之关联的 catch 块将被执行。在 catch 块中,可以访问到异常对象,进而获取异常的详细信息。

    finally 块(可选):无论 try 块中是否抛出了异常,以及是否有与之匹配的 catch 块,finally 块中的代码总会被执行。通常用于资源回收、关闭打开的文件、数据库连接等操作,确保无论程序运行结果如何,都能正确释放资源。

    //示例1
    try {
        int denominator = 0;
        int result = 10 / denominator; // 这将抛出 ArithmeticException
    } catch (ArithmeticException e) {
        System.out.println("Divide by zero error occurred: " + e.getMessage());
    } finally {
        System.out.println("Finally block executed.");
    }
    //在这个例子中,尝试除以零会抛出 ArithmeticException,这个异常会被相应的 catch 块捕获并处理,然后执行 finally 块中的代码。
    ​
    //示例2
    try {
        // 可能抛出多种类型异常的代码
        File file = new File("non_existent_file.txt");
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);
        String line = br.readLine();
    } catch (FileNotFoundException e) {
        // 处理找不到文件异常
        System.out.println("File not found: " + e.getMessage());
    } catch (IOException e) {
        // 处理读取文件时发生的其他IO异常,如读取错误、缓冲区溢出等
        System.out.println("An IO error occurred: " + e.getMessage());
    } finally {
        // 清理资源,如关闭文件流
        try {
            if (br != null) {
                br.close();
            }
        } catch (IOException ex) {
            System.out.println("Error closing the reader: " + ex.getMessage());
        }
    }
    //在上述代码中,try 块中包含了可能导致 FileNotFoundException 和 IOException 的代码。当出现 FileNotFoundException 时,第一个 catch 子句会被执行;如果发生了 IOException 但不是 FileNotFoundException(例如读取过程中出现问题),则第二个 catch 子句会被执行。
    ​
    //需要注意的是,Java 7及更高版本引入了一种更简洁的异常处理方式,即使用一个多异常捕获的 catch 子句,可以捕获并处理多种类型的异常,如下所示:
    catch (FileNotFoundException | IOException e) {
        System.out.println("An error occurred: " + e.getMessage());
    }

  6. String 类是不可变的(immutable),并且 JVM 对 String 对象有一个常量池(String Pool)来保存相同内容的字符串对象,以节省内存和提高性能。

    JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化。字符串常量池存在于方法区

    1)为字符串开辟一个字符串常量池,类似于缓存区。

    2)创建字符串常量时,首先坚持字符串常量池是否存在该字符串。

    3)存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中。

    //
    String a = "abc";
    String b = "abc";
    String c = new String("abc");
    //a和b是同一元素 c则不同
    a == b//true ==比较引用数据类型的地址值
    a == c//false

    常见面试题:String str4 = new String(“abc”) 创建多少个对象?

    1、在常量池中查找是否有“abc”对象。

    1)有则返回对应的引用实例;

    2)没有则创建对应的实例对象。

    2、在堆中 new 一个 String("abc") 对象。

    3、将对象地址赋值给str4,创建一个引用。

    所以,常量池中没有“abc”字面量则创建两个对象,否则创建一个对象,以及创建一个引用。

    String str1 = new String("A"+"B") ; 会创建多少个对象?

    String str2 = new String("ABC") + "ABC" ; 会创建多少个对象?

    str1:

    字符串常量池:"A","B","AB" : 3个

    堆:new String("AB") :1个

    引用: str1 :1个

    总共 : 5个

    str2 :

    字符串常量池:"ABC" : 1个

    堆:new String("ABC") :1个

    引用: str2 :1个

    总共 : 3个

    字符串内部使用字符数组存储的,下面说明字符串不同的创建方法

    String m = "hello,world";
    String n = "hello,world";
    String u = new String(m);
    String v = new String("hello,world");
    ​
    m==n;//true
    m==u;//false
    m==v;//false
    u==v;//false

    1、会分配一个11长度的char数组,并在常量池分配一个由这个char数组组成的字符串,然后由m去引用这个字符串。

    2、用n去引用常量池里边的字符串,所以和n引用的是同一个对象。

    3、生成一个新的字符串,但内部的字符数组引用着m内部的字符数组。

    4、同样会生成一个新的字符串,但内部的字符数组引用常量池里边的字符串内部的字符数组,意思是和u是同样的字符数组。

    使用图来表示的话,情况就大概是这样的(使用虚线只是表示两者其实没什么特别的关系): img

  7. 堆、栈、方法区

    img

    1、堆

    1)存储的是对象,每个对象都包含一个与之对应的class。

    2)JVM只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身。

    3)对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定。

    2、栈

    1)每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象)。

    2)每个栈中的数据(原始类型和对象引用)都是私有的。

    3)栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。

    4)数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失。

    3、方法区

    1)静态区,跟堆一样,被所有的线程共享。

    2)方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。

    字符串常量池则存在于方法区

  8. 常见的类的线程安全问题

    类名
    ArrayList不是线程安全的,如果需要线程安全的列表,可以使用 Collections.synchronizedList(new ArrayList<>())
    StringBuffer线程安全,因为它的方法是同步的
    Vector线程安全,因为它的方法是同步的
    HashMap不是线程安全的。如果需要线程安全的映射,可以使用 Collections.synchronizedMap(new HashMap<>())ConcurrentHashMap
    PropertiesProperties 类是线程安全的,因为它继承了 HashtableHashtable 的方法是同步的
    StringBuilder不是线程安全的
  9. StringBuilder和StringBuffer

    • String:不可变字符串;

    • StringBuffer:可变字符串、效率低、线程安全

    • StringBuilder:可变字符串、效率高、线程不安全;默认长度是16

      img

      因为 StringBuffer 的所有公开方法都是 synchronized 修饰的,而 StringBuilder 并没有。

      • 既然 StringBuffer是线程安全的,它的所有公开方法都是同步的,StringBuilder 是没有对方法加锁同步的,所以毫无疑问,StringBuilder的性能要远大于StringBuffer。

  10. 依赖注入(DI)是Spring框架的核心概念之一,它的主要目标是通过容器来管理和注入对象之间的依赖关系,从而解耦组件之间的依赖关系,降低耦合度,提高代码的灵活性和可维护性。

    依赖注入不会增大程序的规模,它实际上可以帮助简化代码和减少重复性的代码。

    依赖注入不是面向对象技术的替代品,而是一种补充和实现方式。

    依赖注入的核心思想是通过配置或者注解来管理对象之间的依赖关系,从而让程序员专注于业务逻辑而非对象的创建和管理。

    依赖注入的目标是在代码之外管理程序组件间的依赖关系。

  11. 修饰符

    • private:私有访问修饰符,类中的私有成员只能在该类内部访问。

    • public:公共访问修饰符,类中的公共成员可以被任何其他类访问。

    • package:包访问修饰符,没有关键字直接表示包访问权限,类成员默认具有包私有访问权限。

    • static:静态修饰符,用于定义类级别的变量(静态变量)和方法(静态方法),它们属于类而不是对象,可以通过类名直接访问。

    所以,如果需要定义一个类域(类变量)或类方法(静态方法),应该使用 static 修饰符。

参考文献:

1.java abstract的用法_abstract在java中的用法-CSDN博客

2.【JAVA】try-catch结构:异常处理的使用_try catch 响应式-CSDN博客

3.彻底搞懂String:字符串常量池_string常量池-CSDN博客

4.StringBuffer和StringBuilder区别详解(Java面试)_stringbuffer和stringbuilder有什么区别-CSDN博客

  • 15
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java是一种面向对象的编程语言,而华为OD(Open Day)是华为举办的为期1-2天的校园招聘活动。在华为OD面试中,通常会有Java方面的问题。 面试者可能会被要求介绍Java的特点和优势,可以提到以下几点:首先,Java是跨平台的,可以在不同的操作系统上运行。其次,Java有丰富的类库和API,开发者可以借助这些工具提高开发效率。再次,Java具有良好的内存管理和垃圾回收机制,可以提高程序的性能和稳定性。此外,Java还有强大的多线程支持和安全性能,可以满足大规模企业级应用的需求。 除了Java的特点,面试者可能还会被要求回答一些具体的 Java 面试题。例如,可能会涉及基本的语法知识,如Java中的数据类型、循环结构、条件语句等等。还可能会涉及到Java的面向对象特性,如封装、继承、多态等。此外,还有可能会问到Java的异常处理、Java的I/O操作、Java集合框架等高级知识点。 在回答这些问题时,面试者应该清晰、简洁地表达自己的思路和观点,尽量避免模棱两可的回答。另外,面试者还可以结合自己的实际项目经验和编码能力,提供具体的案例或示例来支持自己的回答。在面试过程中,沟通能力和解决问题的能力也是重要的评判标准,所以面试者应该积极与面试官互动,展示自己的学习能力和团队合作能力。 总之,在Java华为OD面试中,面试者需要准备好Java基础知识,并能够根据问题灵活作答,展示自己的技术能力和潜力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值