java基础面试题(1)

本文涵盖了Java开发中的一些基础面试题目,包括JDK、JRE、JVM的区别,==与equals()的不同,final关键字的作用,八种基本数据类型,String类的常用方法,IO流的分类,同步与异步的概念,以及面向对象编程的基本概念。此外,还讨论了反射、序列化和深浅克隆的区别,以及Java中throw和throws的用法。

java基础面试题

JDK、JRE、JVM的区别:

jdk:Java开发工具包,包括jre和java开发工具(如:javac编译,运行等命令),是Java开发的最小环境

jre:java运行环境,包括jvm和java类库,是java开发的最小运行环境

jvm:java虚拟机,是java实现跨平台的核心部分,能够运行java开发的语言程序

==和equals()的区别:

  • ==:适用于基本数据类型和引用数据类型

    • 对基本数据类型:比较的是值
    • 对于引用数据类型:比较的是地址
  • equals(): 只适用于引用数据类型

    • 补充:equals():是Object的方法 底层也是比较的地址 ,(多数类重写后可以比较引用数据类型的值)若想比较象的属性值是否相同需要重写equals()方法。例如:String类重写了 而StringBulder没有重写该方法

final 在 java 中有什么作用?

在Java中,final是一个关键字,可以用于修饰类、方法、变量等。final修饰的元素表示该元素不能被修改或继承,具体的作用如下:

final修饰的类不能被继承。如果将一个类声明为final,则不能再创建该类的子类。这样可以避免类被修改或滥用,从而保证类的稳定性和安全性。

final修饰的方法不能被重写。如果将一个方法声明为final,则子类不能对其进行重写。这样可以保证该方法的行为不被改变,从而提高代码的可靠性和安全性。

final修饰的变量表示该变量只能被赋值一次。如果将一个变量声明为final,则该变量的值不能再被修改。这样可以避免变量被意外修改,提高代码的可维护性和可读性。

final修饰的引用类型变量表示该变量只能指向一个对象。如果将一个引用类型变量声明为final,则该变量只能指向初始化时指定的对象,不能再指向其他对象。这样可以确保引用类型变量不会被修改,从而提高代码的可靠性和安全性。但是该对象的属性是可以修改的。

八种基本数据类型:

byte、short、char、int、long、double、float、boolean。

String 类的常用方法都有那些:

  1. isEmpty():返回字符串长度是否为0。
  2. length():返回字符串的长度。
  3. substring(int beginIndex, int endIndex):返回一个新字符串,它是原字符串的一个子字符串。子字符串从指定的 beginIndex 处开始,直到 endIndex - 1 处的字符。
  4. charAt(int index):返回指定索引处的字符。
  5. indexOf(String str):返回字符串中第一次出现的指定子字符串的索引。如果没有找到指定的子字符串,则返回 -1。
  6. lastIndexOf(String str):返回字符串中最后一次出现的指定子字符串的索引。如果没有找到指定的子字符串,则返回 -1。
  7. equals(Object obj):将此字符串与指定的对象比较。如果对象是一个字符串,并且它与此字符串相等,则返回 true;否则返回 false。
  8. equalsIgnoreCase(String anotherString):将此字符串与指定的字符串比较,忽略大小写。
  9. toLowerCase():将所有在此字符串中大写的字符转换为小写。
  10. toUpperCase():将所有在此字符串中小写的字符转换为大写。
  11. trim():返回字符串的副本,忽略前导空白和尾部空白。
  12. startsWith(String prefix):测试此字符串是否以指定的前缀开始。
  13. endsWith(String suffix):测试此字符串是否以指定的后缀结束。
  14. replace(char oldChar, char newChar):返回一个新字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
  15. split(String regex):根据给定的正则表达式拆分此字符串。
  16. concat(String str):将指定的字符串连接到此字符串的末尾。
  17. getBytes():将字符串转换为一个新的字节数组。
  18. toCharArray():将字符串转换为字符数组。
  19. valueOf(Object obj):返回一个字符串表示指定对象的字符串值。
  20. toString():返回此对象本身(它已经是一个字符串!)。

如何将字符串反转

将对象封装到stringBuilder中,调用reverse方法反转。

java 中 IO 流分为几种?

**按流划分:**可以分为输入流和输出流;

**按单位划分:**可以分为字节流和字符流;

字节流:inputStream、outputStream;

字符流:reader、writer;

**按类型:**节点流和处理流。节点流是直接连接到数据源或数据目的地进行数据读写的,处理流是对节点流进行处理的流。节点流处理的是原始的字节或字符数据,处理流处理的是经过加工后的数据。节点流的读写效率一般较高,而处理流则提供了更多的功能和便利性。

什么是同步,什么是异步,什么是阻塞,什么是非阻塞

同步(Synchronous)和异步(Asynchronous)是关于函数调用的结果如何返回的概念。同步调用会一直等待函数返回结果,而异步调用则不会等待函数返回结果,而是立即返回并执行其他操作,当函数返回结果后,会通过回调函数等方式通知调用者。

阻塞(Blocking)和非阻塞(Non-blocking)则是关于函数是否会一直等待结果的概念。阻塞函数会在执行过程中一直等待结果返回,而非阻塞函数会立即返回结果,如果结果还未准备好,则可以继续执行其他操作。

BIO、NIO和AIO是Java中常用的IO模型。

BIO模型是最传统的IO模型,也被称为阻塞IO。在BIO模型中,IO操作是同步阻塞的,即当线程执行IO操作时,线程会一直阻塞,直到IO操作完成。这意味着在BIO模型中,一个线程只能处理一个IO请求。BIO模型的缺点是并发性能比较差,因为当多个线程执行IO操作时,线程的阻塞和唤醒操作会造成较大的系统开销。

NIO模型是Java 1.4中引入的新IO模型,也称为非阻塞IO。在NIO模型中,IO操作是非阻塞的,线程不会一直阻塞等待IO操作完成,而是会继续执行其他操作。NIO模型的核心是通道(Channel)和缓冲区(Buffer)。通过使用通道,可以实现多路复用,即一个线程可以同时处理多个IO请求。NIO模型相对于BIO模型,可以提高系统的并发性能。

AIO模型是Java 1.7中引入的新IO模型,也称为异步IO。在AIO模型中,IO操作是异步的,线程不会一直阻塞等待IO操作完成,而是可以继续执行其他操作。AIO模型的核心是异步通道(AsynchronousChannel)和回调函数(CompletionHandler)。通过使用异步通道,可以实现异步IO操作,当IO操作完成后,会自动调用回调函数进行处理。AIO模型相对于BIO和NIO模型,可以更加高效地处理IO操作。

什么是面向对象

面向对象就是将特定的事务集合进行抽象化处理,在对具体的场景将抽象的封装具体化为特定行为和属性的类。

面向对象的特点:

  • 封装:封装是将对象运行时所需的资源封装在程序对象中。简单来说,就是将内容封装起来,以后再去调用被封装的内容。
  • 继承:可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。
  • 多态:指同一个实体同时具有多种形式,在赋值之后,不同的子类对象调用相同的父类方法,产生的执行结果不同。

抽象类和接口的区别

  • 抽象类:

    • 用abstract修饰
    • 抽象类中可以定义常量,变量,静态方法,普通方法,构造方法,静态方法
    • 派生类通过extnds来继承
    • 抽象类的成员是任何访问权限都可以(默认为默认权限)
    • 封装了数据和运算逻辑
    • 抽象类是描述子类的共同特征
  • 接口:

    • 用interface定义
    • 只能包含常量和抽象方法
    • 实现类通过implements来实现
    • 可以实现多个(体现多个实现)
    • 接口中的成员的访问权限只能是public(默认为public权限)
    • 接口描述的是类的特有特性
    • 没有数据,没有运算逻辑,结构设计工具

线程的声明周期:

在这里插入图片描述

什么是反射

在Java中,反射是指程序在运行时动态地获取类的信息,以及动态地创建对象、调用方法和访问属性的机制。Java中的每个对象都有一个getClass()方法,可以获取该对象的类信息,然后可以通过这个类的信息来动态地创建对象、调用方法和访问属性。

反射的作用是在运行时获取类的信息,从而可以动态地创建对象、调用方法和访问属性。通过反射可以做到以下几点:

  1. 动态地创建对象:通过Class对象的newInstance()方法可以动态地创建一个对象,而不需要在代码中直接使用new关键字。
  2. 动态地获取类信息:通过Class对象可以获取类的所有信息,如类名、父类、接口、构造函数、方法、字段等。
  3. 动态地调用方法:通过Method对象可以动态地调用一个类的方法,可以在运行时根据方法名和参数来调用指定的方法。
  4. 动态地访问属性:通过Field对象可以动态地访问一个类的属性,可以在运行时根据属性名来获取或设置属性的值。

反射在一些框架和库中被广泛使用

反射的常用API:

  1. 获取 Class 对象的方式:
  • 通过 Class 类的静态方法 forName() 获取指定类的 Class 对象;
  • 通过 Object 类的 getClass() 方法获取该对象的 Class 对象;
  • 通过 .class 直接获取 Class 对象。
  1. 获取构造方法:
  • 通过 Class 类的 getConstructor() 方法获取指定构造方法的 Constructor 对象;
  • 通过 Class 类的 getDeclaredConstructors() 方法获取所有构造方法的 Constructor 数组。
  1. 获取方法:
  • 通过 Class 类的 getMethod() 方法获取指定公共方法的 Method 对象;
  • 通过 Class 类的 getDeclaredMethods() 方法获取该类的所有方法(包括私有方法)的 Method 数组。
  1. 获取字段:
  • 通过 Class 类的 getField() 方法获取指定公共字段的 Field 对象;
  • 通过 Class 类的 getDeclaredFields() 方法获取该类的所有字段(包括私有字段)的 Field 数组。
  1. 调用方法:
  • 通过 Method 类的 invoke() 方法调用指定对象的该方法。
  1. 修改字段:
  • 通过 Field 类的 set() 方法设置指定对象的该字段的值;
  • 通过 Field 类的 get() 方法获取指定对象的该字段的值。
  1. Field类:表示类中的一个成员变量,可以获取、设置成员变量的值。
  2. Modifier类:包含了访问修饰符的常量,可以用于判断一个成员变量或方法的修饰符。
  3. Array类:用于操作数组,可以通过反射创建、获取、设置数组的元素。
  4. Package类:表示Java包的信息。
  5. Proxy类:用于创建动态代理对象。
  6. Annotation类:表示Java注解,可以获取注解信息

反射的应用场景:

框架,注解,动态代理,序列化和反序列化

什么是序列化和反序列化

序列化是将数据结构或对象转换为一系列字节,以便它们可以在网络上传输或者在磁盘上保存。序列化的过程包括将对象的状态编码为字节序列,通常采用二进制格式或者一些文本格式,比如JSON或XML。

反序列化则是将序列化的字节流转换回原始的数据结构或对象。这个过程涉及将序列化的字节流解码为原始的对象的状态。在反序列化期间,字节序列被解码以还原原始对象的状态。

序列化和反序列化是用于在分布式系统中传递数据的重要技术。通过序列化和反序列化,可以在不同的进程或者不同的机器之间传递数据,从而实现进程间通信或者分布式系统之间的通信。

阿里巴巴的 fastjson 是一个高性能的 Java 序列化和反序列化框架支持 JSON、XML、Protobuf 等格式的序列化和反序列化。以

序列化: String json = JSON.toJSONString(person);反序列化:Person person = JSON.parseObject(json, Person.class);

什么是深克隆和浅克隆:

浅拷贝:克隆基本变量时,克隆的是变量的值。克隆引用变量时,克隆的是地址,也就是说当被克隆的值改变,被克隆的值也会改变
深克隆:既克隆基本类型变量,又克隆引用类型变量的值;

jdk1.8的Object类的clone()方法可以实现克隆,被克隆的对象需要实现Cloneable接口。需要注意Spring框架的BeanUtils是浅克隆

如何实现深克隆:

使用clone()方法

  1. 实现Cloneable接口,类中的引用属性也需要实现Cloneable接口
  2. 在引用属性的类中重写clone()方法,并将对象强制转换为引用类型对象
  3. 在被克隆的对象中,重写clone方法先将本对象克隆,然后调用引用类型对象的克隆方法赋值给被克隆对象的属性
public class Person implements Cloneable {
    private String name;
    private int age;
    private Address address;

    public Person(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    @Override
    public Person clone() throws CloneNotSupportedException {
        Person person = (Person) super.clone();
        person.address = this.address.clone();
        return person;
    }
}

class Address implements Cloneable {
    private String street;
    private String city;

    public Address(String street, String city) {
        this.street = street;
        this.city = city;
    }

    @Override
    public Address clone() throws CloneNotSupportedException {
        return (Address) super.clone();
    }
}

通过序列化和反序列化来进行深克隆:

final、finally、finalize 有什么区别:

final是java关键字可以修饰类,变量,方法,修饰的类不能被继承,修饰的变量不能重新赋值,修饰的方法不能被重写

finally用于抛异常,finally代码块内语句无论是否发生异常,都会在执行finally,常用于一些流的关闭。

finalize 是 Object 类中的一个方法,它在对象被垃圾回收之前被调用。finalize 方法可以被子类重写

throw和throws的区别:

throw 关键字用于抛出一个异常对象,作用在方法内

throws 关键字只是声明方法可能会抛出哪些异常,实际上并不会一定抛出异常。如果方法中确实出现了异常,那么它会被抛出,并由调用者或者上层代码块的 catch 代码块进行处理。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值