Java面试——基础篇

目录

1、java语言有哪些优点和缺点?

2、JVM 、 JDK 和 JRE的关系

3、为什么说 Java 语言“编译与解释并存”?

4、Java和c++的区别

5、基本数据类型

5.1、java的8种基本数据类型:

5.2、基本类型和包装类型的区别:

5.3、包装类型的缓存机制:

5.4、自动装箱和自动拆箱:

5.5、浮点数运算的精度丢失问题及解决办法:

6、变量

6.1、成员变量与局部变量的区别?

6.2、静态变量有什么作用?

6.3、字符型常量和字符串常量的区别?

7、方法

7.1、静态方法和实例方法的区别:

7.2、静态方法为什么不能调用非静态成员?

7.3、重载和重写的区别:

8、面向对象基础

8.1、面向对象和面向过程的区别:

8.2、创建一个对象用什么运算符?对象实体与对象引用有何不同?

8.3、对象的相等和引用相等的区别:

8.4、构造函数是什么?能否被override?类没有声明构造方法,程序还能正确执行吗?

8.5、面向对象三大特征

8.6、接口和抽象类有什么共同点和区别?

8.7、深拷贝和浅拷贝的区别?什么是引用拷贝?

9、Object类

9.1、Object 类的常见方法有哪些?

9.2、== 和 equals() 的区别:

9.3、为什么重写 equals() 时必须重写 hashCode() 方法?

10、String类

10.1、String 为什么是不可变的?

10.2、String、StringBuffer、StringBuilder 的区别:

10.3、String s1 = new String("abc");这句话创建了几个字符串对象?

10.4、String#intern 方法有什么作用?

10.5、String 类型的变量和常量做“+”运算时发生了什么?

11、异常

 11.1、Exception 和 Error 的区别:

11.2、Checked Exception 和 Unchecked Exception的区别:

11.3、Throwable 类常用方法有哪些?

11.4、try-catch-finally 如何使用?

11.5、finally 中的代码一定会执行吗?

11.6、如何使用 try-with-resources 代替try-catch-finally?

12、泛型的使用方式有哪几种?

13、反射

13.1、反射的使用:

13.2、反射的应用场景:

14、注解的解析方法有哪几种?

15、什么是序列化?什么是反序列化?

16、I/O流

字节缓冲流:

Java 中 3 种常见 IO 模型:


1、java语言有哪些优点和缺点?

优点:

  • 面向对象(封装,继承,多态)
  • 平台无关性( Java 虚拟机实现平台无关性)
  • 支持多线程
  • 具备异常处理和自动内存管理机制
  • 支持网络编程并且很方便
  • 编译与解释并存

缺点:

  • 使用大量的内存:垃圾回收机制需要占用大量内存,可能导致程序的运行速度相对较慢。
  • 不支持底层操作:Java使用虚拟机来实现,无法和操作系统的底层打交道了。
  • 启动时间慢:由于Java程序需要先启动虚拟机,再执行程序,启动时间相对较慢。

2、JVM 、 JDK 和 JRE的关系

  • JDK(Java Development Kit):是 Java 开发工具包,是整个 Java 的核心,它包含了JRE,同时还包含了 javac(编译 java 源码的编译器)、jconsole(基于 JMX 的可视化监控⼯具)、javap(反编译工具)等等。
  • JRE( Java Runtime Environment):是 Java 的运行环境,包含 JVM 及 Java 核心类库。
  • JVM(Java Virtual Machine):Java 虚拟机,是整个 Java 实现跨平台的最核心的部分。所有 Java 程序会首先被编译为 .class 的类文件,这种类文件可以在虚拟机上执行。

3、为什么说 Java 语言“编译与解释并存”?

高级编程语言按照程序的执行方式分为两种:

  • 编译型语言:通过编译器将源代码一次性翻译成可被该平台执行的机器码。一般编译语言的执行速度比较快,开发效率比较低。常见的编译性语言有 C、C++、Go、Rust 等等。
  • 解释型语言:通过解释器一句一句的将代码解释(interpret)为机器代码后再执行。一般开发效率比较快,执行速度比较慢。常见的解释性语言有 Python、JavaScript、PHP 等等。

        Java 语言既具有编译型语言的特征,又有解释型语言的特征。因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(.class 文件),这种字节码必须由 Java 解释器来解释执行。 

4、Java和c++的区别

  • Java 不提供指针直接访问内存,程序内存更加安全。
  • Java 的类单继承的,C++ 支持多重继承;虽然 Java 类不支持多继承,但接口支持多继承。
  • Java 有自动内存管理垃圾回收机制(GC),不需要程序员手动释放无用内存。
  • C++支持方法重载和操作符重载,但是 Java 只支持方法重载(操作符重载增加了复杂性,这与 Java 最初的设计思想不符)。
  • ……

5、基本数据类型

5.1、java的8种基本数据类型:

5.2、基本类型和包装类型的区别:

  • 用途:基本类型一般用来定义一些局部变量和常量,在其他地方比如方法参数、对象属性中一般使用包装类型,并且包装类型可用于泛型,而基本类型不可以。
  • 存储方式:基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中,基本数据类型的成员变量存放在 Java 虚拟机的堆中。包装类型属于对象类型,放在堆中。
  • 占用空间:相比于包装类型, 基本数据类型占用的空间比较小。

  • 比较方式:对于基本数据类型来说,== 比较的是值。对于包装数据类型来说,== 比较的是对象的内存地址。整型包装类对象之间值的比较,需要使用 equals() 方法。

对于不同类型变量的存储问题,有两条黄金法则:

  • 引用类型总是被分配到“堆”上。不论是成员变量还是局部
  • 基础类型总是分配到它声明的地方:成员变量在堆内存里,局部变量在栈内存里。
public class Test {
    // 成员变量,存放在堆中
    int a = 10;
    // 被 static 修饰,也存放在堆中,但属于类,不属于对象
    // JDK1.7 静态变量从永久代移动了 Java 堆中
    static int b = 20;

    public void method() {
        // 局部变量,存放在栈中
        int c = 30;
        static int d = 40; // 编译错误,不能在方法中使用 static 修饰局部变量
    }
}

5.3、包装类型的缓存机制:

   Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True 或 False,两种浮点数类型的包装类 Float,Double 没有实现缓存机制。

        看如下代码:

Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);

        上述代码应输出false。首先第一行代码会发生自动装箱,因此变量i1使用的是缓存中的对象,而i2会新new一个对象出来,故两者不相等。

        如果想比较包装类对象之间值,需要使用equals。

5.4、自动装箱和自动拆箱:

  • 自动装箱:将基本类型用它们对应的引用类型包装起来;
  • 自动拆箱:将包装类型转换为基本数据类型;

        装箱其实就是调用了 包装类的valueOf()方法,拆箱其实就是调用了 xxxValue()方法。

因此,

Integer i = 10 等价于 Integer i = Integer.valueOf(10)

int n = i 等价于 int n = i.intValue();

5.5、浮点数运算的精度丢失问题及解决办法:

        由于底层保存浮点数的机制,会出现小数的精度发生损失的情况,可以使用 BigDecimal 对浮点数的运算,不会造成精度丢失。如:

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");

BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);

System.out.println(x); /* 0.1 */
System.out.println(y); /* 0.1 */
System.out.println(Objects.equals(x, y)); /* true */

6、变量

6.1、成员变量与局部变量的区别?

  • 语法形式
    • 成员变量属于类,而局部变量是方法中定义的变量或参数;
    • 成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;
    • 成员变量和局部变量都能被 final 所修饰。
  • 存储方式
    • 如果成员变量是使用 static 修饰的,那么这个成员变量是属于类的,如果没有使用 static 修饰,这个成员变量是属于类实例的。
    • 而对象存在于堆内存,局部变量则存在于栈内存。

6.2、静态变量有什么作用?

        静态变量也就是被 static 关键字修饰的变量。它可以被类的所有实例共享,无论一个类创建了多少个对象,它们都共享同一份静态变量。也就是说,静态变量只会被分配一次内存,即使创建了多个对象,这样可以节省内存。

        通常情况下,静态变量会被 final 关键字修饰成为常量。

6.3、字符型常量和字符串常量的区别?

  • 形式 : 字符常量是单引号引起的一个字符,字符串常量是双引号引起的 0 个或若干个字符。
  • 含义 : 字符常量相当于一个整型值( ASCII 值),可以参加表达式运算; 字符串常量代表一个地址值(该字符串在内存中存放位置)。
  • 占内存大小:字符常量占 2 个字节; 字符串常量占若干个字节。 

7、方法

7.1、静态方法和实例方法的区别:

  • 调用方式:在外部调用静态方法时,可以使用 类名.方法名 的方式,也可以使用 对象.方法名 的方式,而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象 。
  • 访问限制:静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),不允许访问实例成员(即实例成员变量和实例方法),而实例方法不存在这个限制。

7.2、静态方法为什么不能调用非静态成员?

  1. 静态方法是属于类的,在类加载的时候就会分配内存,可以通过类名直接访问。而非静态成员属于实例对象,只有在对象实例化之后才存在,需要通过类的实例对象去访问。
  2. 在类的非静态成员不存在的时候静态方法就已经存在了,此时调用在内存中还不存在的非静态成员,属于非法操作。

7.3、重载和重写的区别:

  • 重载:同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。
  • 重写:子类对父类方法的重新改造,外部样子不能改变,内部实现逻辑可以改变。

8、面向对象基础

8.1、面向对象和面向过程的区别:

  • 面向过程:把解决问题的过程拆成一个个方法,通过一个个方法的执行解决问题。
  • 面向对象:是一种“万物皆对象”的编程思想,任何物体都可以归为一类事物,而每一个个体都是一类事物的实例,通过调用对象的方法来解决问题。

8.2、创建一个对象用什么运算符?对象实体与对象引用有何不同?

        用new 运算符,new 创建对象实例,对象实例在堆内存中;对象引用指向对象实例,存放在栈内存中。

  • 一个对象引用可以指向 0 个或 1 个对象(一根绳子可以不系气球,也可以系一个气球);
  • 一个对象可以有 n 个引用指向它(可以用 n 条绳子系住一个气球)。

8.3、对象的相等和引用相等的区别:

  • 对象相等一般比较的是内存中存放的内容是否相等。
  • 引用相等一般比较的是指向的内存地址是否相等。

例如:

String str1 = "hello";
String str2 = new String("hello");
String str3 = "hello";
// 使用 == 比较字符串的引用相等
System.out.println(str1 == str2);
System.out.println(str1 == str3);
// 使用 equals 方法比较字符串的相等
System.out.println(str1.equals(str2));
System.out.println(str1.equals(str3));

上述代码执行结果为:

        结果分析:由于==比较的是引用相等,str2字符串会重新new一个string对象,因此引用和str1不同;str3会优先去字符串常量池寻找有无“hello”这个字符串,有的话就直接引用它,所以str3和str1引用相等。而最后两个比较的是字符串内容是否相等,故str1、str2、str3都相等。        

8.4、构造函数是什么?能否被override?类没有声明构造方法,程序还能正确执行吗?

        构造方法是一种特殊的方法,主要作用是完成对象的初始化工作。构造函数可以被重载(overload),但不能被重写(override)

        当一个类没有声明构造方法,程序也是可以正常执行的。 当没有显式声明构造方式时,类会默认声明一个无参构造函数。但如果我们自己添加了类的构造方法(无论是否有参),Java 就不会添加默认的无参构造方法了

8.5、面向对象三大特征

  • 封装:把数据和操作数据的方法封装起来,对数据的访问只能通过已定义的接口。
    • 可以类比平常生活的开车,汽车的底层结构被封装起来,我们无需关心底层,只需要会踩油门、转动方向盘开车即可。
  • 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类,得到继承信息的被称为子类
    • 父类中的私有属性和方法子类是无法访问,只是拥有。
  • 多态:一个对象具有多种状态,具体表现为父类的引用指向子类的实例。
    • 多态存在的3个必要条件: 要有继承关系 要有方法的重写父类引用指向子类对象

8.6、接口和抽象类有什么共同点和区别?

        抽象类和普通类类似,只是无法实例化,存在的意义就是让其他类继承的。抽象类可以包含抽象方法和非抽象方法,其中抽象方法没有具体的实现,而非抽象方法有具体的实现代码。接口是一种定义了一组方法签名的集合,这些方法默认都是公共的抽象方法,不包含具体的实现代码,比抽象类更加抽象。

共同点:

  • 都不能被实例化。(存在的意义就是被继承或实现)
  • 都包含抽象方法。(抽象类也可以没有抽象方法,只要有abstract关键字修饰,但是没意义)

不同点:

  • 用途:
    • 接口主要用于限制类的行为,实现了某个接口就具有了对应的行为。
    • 抽象类主要用于代码复用。
  • 抽象类中可以定义构造函数,接口不能定义构造函数;
  • 一个类只能继承一个类,但是可以实现多个接口。

8.7、深拷贝和浅拷贝的区别?什么是引用拷贝?

  • 浅拷贝:只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。
  • 深拷贝:会创造一个一模一样的对象,新旧对象不共享内存,修改新对象不会影响到原对象。

9、Object类

9.1、Object 类的常见方法有哪些?

        Object 类是一个特殊的类,是所有类的父类。它主要提供了以下 11 个方法:

/**
 * native 方法,用于返回当前运行时对象的 Class 对象,使用了 final 关键字修饰,故不允许子类重写。
 */
public final native Class<?> getClass()
/**
 * native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的HashMap。
 */
public native int hashCode()
/**
 * 用于比较 2 个对象的内存地址是否相等,String 类对该方法进行了重写以用于比较字符串的值是否相等。
 */
public boolean equals(Object obj)
/**
 * native 方法,用于创建并返回当前对象的一份拷贝。
 */
protected native Object clone() throws CloneNotSupportedException
/**
 * 返回类的名字实例的哈希码的 16 进制的字符串。建议 Object 所有的子类都重写这个方法。
 */
public String toString()
/**
 * native 方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
 */
public final native void notify()
/**
 * native 方法,并且不能重写。跟 notify 一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
 */
public final native void notifyAll()
/**
 * native方法,并且不能重写。暂停线程的执行。注意:sleep 方法没有释放锁,而 wait 方法释放了锁 ,timeout 是等待时间。
 */
public final native void wait(long timeout) throws InterruptedException
/**
 * 多了 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒。。
 */
public final void wait(long timeout, int nanos) throws InterruptedException
/**
 * 跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
 */
public final void wait() throws InterruptedException
/**
 * 实例被垃圾回收器回收的时候触发的操作
 */
protected void finalize() throws Throwable { }

9.2、== 和 equals() 的区别:

  • “==”:由于 Java 只有值传递,所以,对于 == 来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址。因此 == 对于基本数据类型来说比较的是值,对于引用数据类型来说比较的是内存地址
  • equals():如果类没有重写equals方法,等价于“==”的效果;如果重写了,则比较的是对象的属性是否相等。

9.3、为什么重写 equals() 时必须重写 hashCode() 方法?

        如果不同时重写的话,可能会出现以下情况:set集合中出现两个相同的对象,即无法去重。

        原因:set集合在进行去重操作时,会先判断两个对象的hashcode是否相等,如果不重写hashcode()方法,就会调用object中的hashcode()方法,返回的是对象内存地址的哈希码,这就意味着两个内容相同的对象,其哈希码会由于内存地址的不同而不同。 两个内容相同的对象哈希码不同,则默认这两个对象不同,都会插入到set集合中,导致set集合有重复对象。

10、String类

10.1、String 为什么是不可变的?

  • 字符串常量池:
    • Java内存中存在一个字符串常量池,是存储字符串对象的特殊内存区域。当创建一个字符串时,如果该字符串已经存在于字符串常量池中,那么就会直接返回这个字符串的引用;如果不存在,则会将该字符串添加到字符串常量池中,并返回新创建的字符串的引用。由于字符串常量池的存在,多个字符串可以共享同一个实例,这样可以节省内存空间。而如果 String 是可变的,那么在修改字符串时,会导致其他使用相同字符串的地方出问题。
  • 安全性:
    • 由于String不可变,因此其在多线程环境下是安全的
  • 缓存哈希值:
    • String 类重写了 hashCode()方法,并且在第一次调用时计算并缓存了字符串的哈希值。由于 String 是不可变的,所以可以保证哈希值的唯一性和一致性

10.2、String、StringBuffer、StringBuilder 的区别:

  • 可变性:
    • String 用于表示字符串,属于不可变类。所以每次对String进行修改都会创建一个新的String对象,导致频繁的内存分配和回收,影响性能。
    • Java提供了StringBuffer StringBuilder两个可变的字符串,用于高效地进行字符串的操作。
  • 原理:
    • String 内部使用字符数组来保存字符串内容,并且该数组是 final 修饰的,当对 String 进行修改时,会创建一个新的 String 对象;
    • StringBuffer 内部也使用字符数组来保存字符串内容,但是该数组没有被 final 修饰,当对 StringBuffer 进行修改时,直接在原有的字符数组上进行操作,不会创建新的对象。
    • StringBuilder 的实现原理与 StringBuffer 相同,唯一的区别是 StringBuilder 不是线程安全的,而 StringBuffer 是线程安全的。

10.3、String s1 = new String("abc");这句话创建了几个字符串对象?

分情况:

  • 如果字符串常量池无该对象:那么会堆中创建两个字符串对象,一个存在字符串常量池中。
  • 如果字符串常量池有该对象:那么只会在堆中创建一个字符串对象。

10.4、String#intern 方法有什么作用?

        intern 是一个 native(本地)方法,其作用是将指定的字符串对象的引用保存在字符串常量池中,可以简单分为两种情况:

  • 如果字符串常量池中保存了对应的字符串对象的引用,就直接返回该引用。
  • 如果字符串常量池中没有保存了对应的字符串对象的引用,那就在常量池中创建一个指向该字符串对象的引用并返回。

10.5、String 类型的变量和常量做“+”运算时发生了什么?

当字符串不加 final 关键字拼接时:

String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";
String str4 = str1 + str2;
String str5 = "string";
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false

执行结果分析:首先明确一点:

        对于编译期可以确定值的字符串,也就是常量字符串 ,jvm 会将其存入字符串常量池。并且,字符串常量拼接得到的字符串常量在编译阶段就已经被存放字符串常量池,这个得益于编译器的优化。

        因此,上述代码中,除了str4的其余字符串都已经存入到字符串常量池中;而str4涉及到两个字符串的拼接,底层会在堆中创建一个新的对象,所以str4和其他字符串的比较都为false。

不过,当字符串使用 final 关键字声明之后,可以让编译器当做常量来处理:

final String str1 = "str";
final String str2 = "ing";
// 下面两个表达式其实是等价的
String c = "str" + "ing";// 常量池中的对象
String d = str1 + str2; // 常量池中的对象
System.out.println(c == d);// true

11、异常

Java 异常类层次结构图概览

 11.1、Exception 和 Error 的区别:

  • Exception:程序本身可以处理的异常,可以通过catch来获取,Exception又可以细分为受检查异常不受检查异常
  • Error:属于程序无法处理的错误。

11.2、Checked Exception 和 Unchecked Exception的区别:

  • Checked Exception:受检查异常,Java 代码在编译过程中,如果受检查异常没有被 catch或者throws 关键字处理的话,就没办法通过编译。除了RuntimeException及其子类以外,其他的Exception类及其子类都属于受检查异常 。常见的受检查异常有:IO 相关的异常、ClassNotFoundExceptionSQLException...。
  • Unchecked Exception:不受检查异常,Java 代码在编译过程中 ,我们即使不处理不受检查异常也可以正常通过编译。RuntimeException 及其子类统称为不受检查异常,常见的有:
    • NullPointerException(空指针错误)
    • ArrayIndexOutOfBoundsException(数组越界错误)
    • ClassCastException(类型转换错误)
    • IllegalArgumentException(参数错误比如方法入参类型错误)
    • NumberFormatException(字符串转换为数字格式错误)
    • ArithmeticException(算术错误)
    • SecurityException (安全错误比如权限不够)
    • UnsupportedOperationException(不支持的操作错误比如重复创建同一用户)

11.3、Throwable 类常用方法有哪些?

  • String getMessage(): 返回异常发生时的简要描述
  • String toString(): 返回异常发生时的详细信息
  • String getLocalizedMessage(): 返回异常对象的本地化信息。使用 Throwable 的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与 getMessage()返回的结果相同
  • void printStackTrace(): 在控制台上打印 Throwable 对象封装的异常信息

11.4、try-catch-finally 如何使用?

  • try块:用于捕获异常。其后可接零个或多个 catch 块,如果没有 catch 块,则必须跟一个 finally 块。
  • catch块:用于处理 try 捕获到的异常。
  • finally 块:无论是否捕获或处理异常,finally 块里的语句都会被执行。当在 try 块或 catch 块中遇到 return 语句时,finally 语句块将在方法返回之前被执行。

11.5、finally 中的代码一定会执行吗?

        不一定,在某些情况下,finally 中的代码不会被执行,如:

  • 在执行finally的代码之前虚拟机被终止了。
  • 程序所在的线程死亡。
  • 关闭CPU。

11.6、如何使用 try-with-resources 代替try-catch-finally?

        try-with-resources 是 Java 7 引入的一种语法结构,用于自动关闭实现了 AutoCloseable 接口的资源。它可以代替传统的 try-catch-finally 结构来处理资源的释放。

优点:

  • 简化了代码结构:不再需要显式地编写 finally 块来关闭资源。
  • 自动确保资源的正确关闭:无论是否发生异常,都会自动调用资源的 close() 方法进行关闭。
  • 支持多个资源同时关闭:可以在 try 后面的括号内声明多个资源,并按照声明顺序逆序关闭。

12、泛型的使用方式有哪几种?

        使用泛型,可以增加代码的灵活性和安全性,使得代码更加通用和易于维护

  • 泛型类:定义一个类时,可以在类名后面加上尖括号<>,并在其中指定类型参数。
  • 泛型接口:与泛型类类似,可以在接口名后面加上尖括号<>,并在其中指定类型参数。然后在实现该接口时,需要指定具体的类型。
  • 泛型方法:即在方法返回值前面加上尖括号<>,并在其中指定类型参数。

13、反射

13.1、反射的使用:

        反射是java语言的一个特性,它允程序在运行时动态获取和调用类的属性和方法。

        要使用反射,需要先获取类的class对象(字节码对象),有三种方式:

  • Class.forName("全类名");
  • 类名.class;
  • 类实例对象.getClass();

        接下来就可以通过具体的API调用获取到详细的属性或者方法:

  • 获取构造函数:getConstructors()等方法。
  • 获取类成员变量:getFields()等方法。
  • 获取类成员方法:getMethods()等方法。

13.2、反射的应用场景:

        Spring 框架的 IOC(动态加载管理 Bean)、加载数据库驱动:

Class.forName("com.mysql.cj.jdbc.Driver");

、IDEA的方法提醒都需要用到反射机制。 

14、注解的解析方法有哪几种?

        注解只有被解析之后才会生效,常见的解析方法有两种:

  • 编译期直接扫描:编译器在编译 Java 代码的时候扫描对应的注解并处理,比如某个方法使用@Override 注解,编译器在编译的时候就会检测当前的方法是否重写了父类对应的方法。
  • 运行期通过反射处理:像框架中自带的注解(比如 Spring 框架的 @Value@Component)都是通过反射来进行处理的。

15、什么是序列化?什么是反序列化?

        如果我们需要持久化 Java 对象比如将 Java 对象保存在文件中,或者在网络传输 Java 对象,这些场景都需要用到序列化。

简单来说:

  • 序列化:将数据结构或对象转换成二进制字节流的过程。
  • 反序列化:将在序列化过程中所生成的二进制字节流转换成数据结构或者对象的过程。

        序列化协议对应于OSI 七层协议模型中表示层。

        对于不想进行序列化的变量,使用 transient 关键字修饰。

  • transient 只能修饰变量,不能修饰类和方法。
  • static 变量不属于任何对象(Object),所以无论有无 transient修饰,均不会被序列化。

16、I/O流

        I/OInput/Output,数据输入到计算机内存的过程即输入,反之输出到外部存储(比如数据库,文件,远程主机)的过程即输出。数据传输过程类似于水流,因此称为 IO 流。IO 流在 Java 中分为输入流输出流,而根据数据的处理方式又分为字节流字符流

        Java I/O流中有四个抽象类基类,其架构如下图:

        字节流适合传输所有类型的文件,如音频、视频、图片、文本文件的复制转移等。字符流只适合传输纯文本文件,如txt、java文件等。

字节缓冲流:

        字节流在调用 write(int b)read() 方法的时候,一次只能读取一个字节。由于字节缓冲流内部有缓冲区(字节数组),因此,字节缓冲流会先将读取到的字节存放在缓存区,大幅减少 IO 次数,提高读取效率。

Java 中 3 种常见 IO 模型:

  • BIO (Blocking I/O):同步阻塞 IO 模型中,应用程序发起 read 调用后,会一直阻塞,直到内核把数据拷贝到用户空间。在高并发场景下效率较低。

  • NIO (Non-blocking I/O):同步非阻塞 IO 模型,应用程序会一直发起 read 调用,等待数据从内核空间拷贝到用户空间的这段时间里,线程依然是阻塞的,直到在内核把数据拷贝到用户空间。通过轮询操作,避免了一直阻塞,但是不断发起调用消耗大量cpu资源。

  • AIO (Asynchronous I/O):异步 IO 模型,应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/349910.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DataKit迁移MySQL到openGauss

前言 本文将分享DataKit迁移MySQL到openGauss的项目实战&#xff0c;供广大openGauss爱好者参考。 1. 下载操作系统 https://www.openeuler.org/zh/download https://support.huawei.com/enterprise/zh/doc/EDOC1100332931/1a643956 https://support.huawei.com/enterprise…

深度学习(5)---自注意力机制

文章目录 一、输入与输出二、Self-attention2.1 介绍2.2 运作过程2.3 矩阵相乘理解运作过程 三、位置编码四、Truncated Self-attention4.1 概述4.2 和CNN对比4.3 和RNN对比 一、输入与输出 1. 一般情况下在简单模型中我们输入一个向量&#xff0c;输出结果可能是一个数值或者一…

css 中 flex 布局最后一行实现左对齐

问题 flex 布局最后一行没有进行左对齐显示&#xff1a; <div classparent><div classchild></div><div classchild></div><div classchild></div><div classchild></div><div classchild></div><div…

Linux中禅道12.5一键部署安装过程笔记

1. Linux中禅道12.5一键部署安装过程笔记 文章目录 1. Linux中禅道12.5一键部署安装过程笔记1. 安装1.将安装包直接解压到/opt目录下2. Apache和Mysql常用命令3. 访问和登录禅道4. 其他 2. 访问数据库1. 网页登录数据库2. 命令行连接数据库 3. 9.2.stable版本起Linux一键安装包…

设计模式_装饰器模式_Decorator

生活案例 咖啡厅 咖啡定制案例 在咖啡厅中&#xff0c;有多种不同类型的咖啡&#xff0c;客户在预定了咖啡之后&#xff0c;还可以选择添加不同的调料来调整咖啡的口味&#xff0c;当客户点了咖啡添加了不同的调料&#xff0c;咖啡的价格需要做出相应的改变。 要求&#xff…

girhub添加 SSH 密钥

1 打开终端 输入 ssh-keygen -t rsa -b 4096 -C "github邮箱地址"如果不需要密码可以一路回车 出现这个页面就是生存成功了 open ~/.ssh // 打开.ssh 找到id_rsa.pub复制出内容新建ssh密钥输入内容,保存即可

jmeter下载及安装配置

前言 本文是在win10环境下安装使用jmeter&#xff0c;jmeter可以运行在多平台上Windows和Linux。 环境准备&#xff1a; java 1.8 jmeter 5.1.1 jmeter环境 jmeter环境依赖JAVA环境&#xff0c;需安装JDK1.8环境&#xff0c;JDK环境安装网上一大堆教程&#xff0c;我这里就…

Socket实现服务器和客户端

Socket 编程是一种用于在网络上进行通信的编程方法&#xff0c;以下代码可以实现在不同主机之间传输数据。 Socket 编程中服务器端和客户端的基本步骤&#xff1a;服务器端步骤&#xff1a; 1.创建 Socket&#xff1a; int serverSocket socket(AF_INET, SOCK_STREAM, 0);…

详讲api网关之kong的基本概念及安装和使用(一)

什么是api网关 前面我们聊过sentinel&#xff0c;用来限流熔断和降级&#xff0c;如果你只有一个服务&#xff0c;用sentinel自然没有问题&#xff0c;但是如果是有多个服务&#xff0c;特别是微服务的兴起&#xff0c;那么每个服务都使用sentinel就给系统维护带来麻烦。那么网…

附1:k8s服务器初始化

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 关联文章&#xff1a; 《RKE快速搭建离线k8s集群并用rancher管理界面》 《附2&#xff1a;rke安装的k8s集群新增主机》 1.创建…

IDEA使用技巧总结(强迫症福音+新手必看)

前言 本文主要整理与分享个人在使用IDEA做Java开发时做的各种配置&#xff0c;算是几年来的总结。 本人使用的 idea 版本比较老了&#xff0c;2019.1 版本&#xff0c;JDK 版本也老&#xff0c;1.8 版本&#xff0c;主打的是情怀不同版本的 idea 影响不大&#xff0c;基本上在设…

【C++】list讲解及模拟

目录 list的基本介绍 list模拟实现 一.创建节点 二.迭代器 1.模版参数 2.迭代器的实现&#xff1a; a. ! b. c. -- d. *指针 e.&引用 整体iterator (与const复用)&#xff1a; 三.功能实现 1.模版参数 2.具体功能实现&#xff1a; 2.1 构造函数 2.2 begi…

【oracle】oracle客户端及oracle连接工具

一、关于oracle客户端 1.1 Oracle Client 完整客户端 包含完整的客户端连接工具。 包很大&#xff0c;需要安装 1.2 instantclient 即时客户端 是 Oracle(R) 发布的轻量级数据库客户端&#xff0c;减少甚至只包含几个文件&#xff0c;您无需安装标准的客户端&#xff0c;就可以…

Element UI样式修改之NavMenu导航菜单箭头样式修改

UI设计稿给的菜单箭头样式可能与我们饿了么组件NavMenu的菜单箭头样式不一致,目前我们侧边导航菜单的上下翻转箭头如下所示: 希望得到如下的结果: 找到饿了么Icon里我们想要向下箭头,F12后复制content内容content: “\e790”; content: "\e790";然后将默认的c…

【Delphi】程序实现Windows电脑关机、重启、注销(源代码)

目录 一、API函数说明 1. GetCurrentProcess 2. OpenProcessToken 3. LookupPrivilegeValue 4. AdjustTokenPrivileges 5. ExitWindowsEx 二、Delphi实现源代码 在日常软件开发中&#xff0c;可能会遇到通过程序自动关闭电脑&#xff0c;在早期Windows 9x下&#xff0c;…

西安石油大学C++上机实验汇总

考试题难度就像第三章第五章课后题的难度 基础知识一定要掌握&#xff01;&#xff01;&#xff01; 上机一&#xff1a;类与对象程序设计&#xff08;2 学时&#xff09; 上机目的 掌握声明类的方法。掌握类和类的成员的概念以及定义对象的方法。掌握构造函数和析构函数的…

家居图册制作方法,快来看看

​随着家居设计的流行&#xff0c;越来越多的人开始关注家居装饰和家居用品。据统计&#xff0c;家居市场每年的销售额逐年增长。而家居图册作为家居装饰的重要组成部分&#xff0c;其制作方法也备受关注。 那要怎么制作呢&#xff1f;准备好这个工具&#xff1a;FLBOOK在线制作…

百度Apollo | 实车自动驾驶:感知、决策、执行的无缝融合

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《linux深造日志》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下…

风口抓猪-借助亚马逊云科技EC2服务器即刻构建PalWorld(幻兽帕鲁)私服~~~持续更新中

Pocketpair出品的生存类游戏《幻兽帕鲁》最近非常火&#xff0c;最高在线人数已逼近200万。官方服务器亚历山大&#xff0c;游戏开发商也提供了搭建私人专用服务器的方案&#xff0c;既可以保证稳定的游戏体验&#xff0c;也可以和朋友一起联机游戏&#xff0c;而且还能自定义经…

大创项目推荐 题目:基于LSTM的预测算法 - 股票预测 天气预测 房价预测

文章目录 0 简介1 基于 Keras 用 LSTM 网络做时间序列预测2 长短记忆网络3 LSTM 网络结构和原理3.1 LSTM核心思想3.2 遗忘门3.3 输入门3.4 输出门 4 基于LSTM的天气预测4.1 数据集4.2 预测示例 5 基于LSTM的股票价格预测5.1 数据集5.2 实现代码 6 lstm 预测航空旅客数目数据集预…