Java面经09.30--一塌糊涂

0.什么是线程安全,怎么保证线程安全?

当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安全的。

确保线程安全的方法主要有以下几种:

  1. 互斥锁(Mutex):使用锁机制来控制对共享资源的访问,确保同一时间只有一个线程可以访问该资源。

  2. 读写锁(Read-Write Lock):允许多个线程同时读取共享资源,但在写入时会阻塞其他线程的读取和写入。

  3. 线程局部存储(Thread-local Storage):每个线程都有自己的变量副本,避免了多个线程之间的共享。

  4. 不可变对象(Immutable Object):创建不可变对象,确保对象一旦创建后不能被修改,避免了并发修改带来的问题。

  5. 使用原子操作(Atomic Operations):一些数据结构和操作提供原子性,确保在执行时不会被其他线程干扰。

  6. 高层并发工具:使用现有的高层次并发库,如 Java 的 java.util.concurrent 包,提供了许多线程安全的集合和工具。

1.什么是Java的多态特性?

多态是指同一个接口或父类引用变量可以指向不同的对象实例,并根据实际指向的对象类型执行相应的方法。它允许同一方法在不同对象上表现出不同的行为,是面向对象编程(OOP)的核心特性之一。

1.1.多态的优点

通过多态,程序可以灵活地处理不同类型的对象,降低代码耦合度,增强系统的可扩展性。新增子类或实现类时,无需修改原有代码,只需通过接口或父类引用调用即可。

1.2.多态的意义

多态其实是一种抽象行为,它可以让程序员在抽象类的基础上实现具体的实现类,提高了编程的可扩展性。

代码示例:

class Person {
   void work() {
       System.out.println("工作");
   }
}

class Student extends Person {
   @Override
   void work() {
       System.out.println("上学");
   }
}

public class Test {
   public static void main(String[] args) {
       Person person = new Student();
       person.work(); // 输出 "上学"
   }
}

个人理解助记:不同的人物角色在日常生活中的职责都不一样,如果每个角色写一个具体实现类的话不仅代码很多重复赘余,如果职责改变了需要修改代码也很麻烦。

注意混淆!!!!=>多重继承

Java是不支持多继承的,因为多继承会导致菱形继承(也叫钻石继承)问题,Java之父吸取了C++的教训,因此不支持多继承。

什么是菱形继承呢?

如图所示,BC继承了A,然后D继承了BC,假设此时要调用D内定义在A的方法,因为B和C都有不同的实现,此时就会出现歧义,不知道应该调用哪个了。

2.Vue的原理

vue.js是一个流行的前端框架,主要用于构建用户界面和单页应用。它的底层概念涉及如下几个关键概念:

2.1.响应式系统

Vue 的核心是其响应式系统。它使用了 Object.defineProperty(在 Vue 2 中)和 Proxy(在 Vue 3 中)来实现数据绑定(vue3中使用了Proxy代替了Object.defineProperty)。主要步骤包括:

  • 数据劫持:当你定义一个 Vue 实例时,Vue 会遍历数据对象的属性,并使用 Object.definePropertyProxy 创建 getter 和 setter。这些 getter 和 setter 允许 Vue 监听数据的变化。

  • 依赖收集:当组件访问某个数据属性时,Vue 会收集这个属性的依赖(即所有依赖于这个属性的组件)。这通常是在 getter 中进行的。

  • 触发更新:当数据发生变化时,setter 会被触发,Vue 会通知所有依赖这个数据的组件进行重新渲染。

2.2. 虚拟 DOM

Vue 使用虚拟 DOM 来优化性能。虚拟 DOM 是对真实 DOM 的一种抽象表示,它通过 JavaScript 对象的形式存储。

  • 渲染:当组件需要渲染时,Vue 会创建一个虚拟 DOM 树。

  • Diff 算法(vue3引入):当数据变化时,Vue 会生成新的虚拟 DOM 树,并与旧的虚拟 DOM 树进行比较。这种比较的过程称为 diff。它会找出哪些部分发生了变化,然后只更新那些部分,而不是重新渲染整个 DOM。

2.3. 组件化

Vue 采用了组件化的设计思想。每个 Vue 组件都有自己的模板、逻辑和样式,使得开发过程更加模块化和可维护。

  • 组件生命周期:每个组件都有一系列的生命周期钩子,如 createdmountedupdateddestroyed,允许开发者在特定的时间点执行代码。

  • 插槽:组件可以使用插槽(slots)来实现更灵活的内容分发,让父组件能够传递内容到子组件中。

2.4. 模板编译

Vue 使用模板语法来定义组件的 UI,模板在运行时被编译成渲染函数。

  • 指令:Vue 提供了一些内置指令(如 v-ifv-forv-bind 等),这些指令在编译过程中被转化为相应的渲染逻辑。

  • 插值:模板中的数据插值(如 {{ message }})在编译后会被转化为相应的 JavaScript 表达式。

2.5. Vue Router 和 Vuex

  • Vue Router:用于处理路由的管理,使得单页应用能够在不同的视图间导航。

  • Vuex:是一个状态管理模式,用于在多个组件之间共享状态,使得应用的状态管理更加集中和可预测。

2.6. 插件机制

Vue 提供了一个强大的插件系统,可以通过 Vue.use() 来注册插件。插件可以添加全局功能,如全局组件、指令或混入等。

3.JVM的参数

  • -Xmx:用于设置JVM的最大堆内存大小。例如,"-Xmx512m"表示将最大堆内存设置为512MB
  • -Xms:用于设置JVM的初始堆内存大小。例如,"-Xms256m"表示初始堆内存为256MB
  • -Xss:用于设置每个线程的堆栈大小。例如,"-Xss1m"表示将堆栈大小设置为1MB。.
  • -Xmn:用于设置年轻代的堆内存大小。例如,"-Xmn256m"表示将年轻代的堆内存设置为256MB.
  • -XX:PermSize:用于设置永久代的初始大小。在Java 8及之后的版本中,永久代已被元空间(Metaspace)取代。
  • -XX:MaxPermSize:用于设置永久代的最大大小。在Java 8及之后的版本中,永久代已被元空间(Metaspace)取代。
  • -XX:MaxMetaspaceSize:用于设置元空间的最大大小。在Java 8及之后的版本中,用于控制元空间大小。
  • -XX:NewRatio:用于设置年轻代与老年代的内存比例。例如,“-XX:NewRatio=2"表示年轻代占整个堆内存的1/3,老年代占2/3。
  • -XX:MaxTenuringThreshold:用于设置对象在年轻代中经历多少次垃圾回收后晋升到老年代。默认值通常为15。
  • -XXSurvivorRatio:用于设置Eden区和Survivor区的内存比例。例如,"-XKSurvivorRatio=8"表示Eden区占整个年轻代的8/10,每个Survivor区占1/10。
  • -XX:+UseConcMarkSweepGC:启用CMS (Concurrent Mark-Sweep)垃圾回收器。
  • -XX:+UseG1GC:启用G1 (Garbage-First)垃圾回收器。
  • -XX:MaxGCPauseMillis:用于设置垃圾回收的最大暂停时间目标。
  • -XX:ParallelGCThreads:用于设置并行垃圾回收线程的数量。
  • -XX:+PrintGCDetails:打印垃圾回收详细信息。

3.1. 为什么要进行JVM参数调优?

对 JVM 参数进行调优的目的是为了提高 Java 应用程序的性能和稳定性,避免内存不足、垃圾回收(GC)频繁导致的性能下降等问题。合理地配置 JVM 参数,可以充分利用系统资源、优化内存分配、减少垃圾回收的开销,进而提升应用的响应速度和处理能力。

4.什么是反射机制,说说你的理解?

Java的反射机制是一种强大的特性,允许程序在运行时查询和操作类的属性和方法。通过反射,程序可以动态地加载类、创建对象、调用方法、访问字段等。

4.1.反射机制的主要特点:

  1. 动态性:可以在运行时决定使用哪个类或方法,而不需要在编译时确定。
  2. 灵活性:可以访问私有成员、调用私有方法,打破了封装的限制。
  3. 通用性:适用于不确定具体类的情况,比如通过配置文件、注解等动态创建对象。

4.2.使用反射机制的场景:

  1. 框架设计:许多框架(如Spring、Hibernate)使用反射来实现依赖注入、对象持久化等功能。
  2. 插件系统:需要动态加载和调用不同的类,便于扩展和维护。
  3. 开发工具:如调试工具、测试框架,可以使用反射来检查对象状态、调用方法等。
  4. 序列化与反序列化:在将对象转化为字节流或从字节流重建对象时,可以使用反射来访问对象的字段。

4.3.注意事项:

  • 反射会带来一定的性能开销,因为它需要在运行时进行类型检查。
  • 使用反射访问私有成员可能导致代码难以维护,降低了封装性。
  • 过度使用反射可能会导致代码的可读性和可理解性降低。

5.说说你对Java泛型的理解

5.1. 泛型的基本概念

泛型允许你在定义类、接口或方法时使用“参数化类型”,即将数据类型作为参数传递。它的核心思想是允许程序员编写的代码可以适用于各种数据类型,而不必重复编写相同的代码逻辑。

示例代码如下:

public class Box<T> {
    private T item;
    
    public void setItem(T item) {
        this.item = item;
    }
    
    public T getItem() {
        return item;
    }
}

//使用泛型时可以指定类型
Box<String> stringBox = new Box<>();
stringBox.setItem("Hello");
String str = stringBox.getItem();  // 不需要强制类型转换

如果是普通的类的话,当你取出这个对象的时候需要进行强制类型转换,如果处理不当容易报错。

5.2. 泛型的通配符

Java 泛型支持通配符,用于表示不确定的类型,常用的通配符有 ?? extends T? super T

5.2.1 ? 通配符

? 表示未知的类型,它可以代表任何类型。常用于泛型方法和集合的参数。示例如下:

//此方法接受任何类型的list
public static void printList(List<?> list) {
    for (Object obj : list) {
        System.out.println(obj);
    }
}
5.2.2 ? extends T 上限通配符

? extends T 表示类型是 TT 的子类型。常用于只读取数据的场景,保证数据类型的范围。

//该方法可以接受 Number 类型的 List,或其子类(如 Integer、Double)的 List。
public static void printNumbers(List<? extends Number> list) {
    for (Number number : list) {
        System.out.println(number);
    }
}
5.2.3 ? super T 下限通配符

? super T 表示类型是 TT 的超类型。常用于写入数据的场景,确保能够接受 T 类型或其父类的对象。

public static void addNumber(List<? super Integer> list) {
    list.add(1);  // 可以添加 Integer 类型的对象
}

5.3. 泛型的限制

尽管泛型非常强大,但在使用时也有一些限制:

  • 基本类型不能作为泛型类型参数: 例如,List<int> 是非法的。必须使用对应的包装类型 List<Integer>
  • 类型擦除: Java 的泛型在编译时会进行类型擦除,即所有的泛型信息在编译后都会被去除,这意味着泛型只在编译时有效,运行时无法获取泛型的具体类型。

5.4. 泛型和继承

在 Java 中,泛型类型之间没有继承关系。即使 IntegerNumber 的子类,List<Integer> 并不是 List<Number> 的子类型。例如,不能把 List<Integer> 传递给期望 List<Number> 的方法。

错误示例:

List<Integer> integers = new ArrayList<>();
List<Number> numbers = integers;  // 编译错误

5.5. 总结作用

  • 类型安全:泛型允许在编译时进行类型检查,确保在使用集合或其他泛型类时,不会出现类型不匹配的问题,减少了运行时的classcastException错误。
  • 代码重用:泛型使代码可以适用于多种不同的类型,减少代码重复,提升可读性和维护性。
  • 消除显式类型转换:泛型允许在编译时指定类型参数,从而消除了运行时需要显式类型转换的麻烦。

6.总结

非常糟糕的一次面试体验,快问快答式的面试,除了问到关于个人项目的时候回答出来了点东西,然后从问Java基础开始,连续问了十几道题,每道题超3秒没回答出来就跳过问下一道了,没给思考的时间,主要考察你对技术知识的掌握度,当时问的每个东西都感觉挺熟悉,但是就是几乎啥也没答上来,草草地就结束了这次的面试,当时忘记录音了,因为是国庆前的最后一个面试,面完之后整个人有点颓,有些问题记不清了,记起来再补充吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值