Skip to content

Java ​


JDK、JRE、JVM分别是什么 ​

JDK 是 Java 语言的软件开发工具包,包含了JRE,编译器和其他的工具,可以让开发者开发、编译、执行 Java 程序;JRE 是 Java 运行环境,包含了 JVM,以及Java核心库, JRE是 Java运行必不可少的;JVM 是Java虚拟机,是Java的运行环境。

重载和覆盖(重写)有什么区别 ​

重载:重载发生在一个类中,其中参数类型和参数个数不同,方法名必须一样,方法的返回值类型可以不一样。

重写:重写发生在子类和父类之间,是子类覆盖父类的方法,子类的方法名,参数类型和参数的个数必须和父类相同,如果有返回值,则返回值类型必须相同

简述抽象类和接口的区别 ​

  • 抽象类可以有构造方法,接口中不能有构造方法。
  • 抽象类中可以有普通成员变量,接口中没有普通成员变量,接口中全是静态变量。
  • 抽象类中可以包含静态方法,接口中不能包含静态方法。
  • 一个类可以实现多个接口,但只能继承一个抽象类。
  • 实现接口时里面的方法必须实现而抽象类则不需要。
  • 抽象类中的方法不一定是抽象方法,接口中的方法一定是抽象方法。

什么是继承 ​

基于一个已存在的类,使用 extends 关键字创建一个新的类,已存在的类即父类,新的类即子类。

特征:

  • 子类拥有父类非 private 的属性和方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。(即重写)

描述 Java中的数据类型 ​

数据类型分为基本数据类型和引用数据类型:

基本数据类型(共八种,四个整数型,两个浮点型,一个字符类型,一个布尔型):

  1. byte:字节整数,数据类型是8位、有符号的整数,默认值0。
  2. short:短整型,16 位、有符号的整数,默认值0。
  3. int:整型,32位、有符号的整数,默认值0。
  4. long:长整型, 64 位、有符号的整数,默认值0L。
  5. float:单精度浮点型,32位的浮点数,默认值0.0f。
  6. double:双精度浮点型,64位的浮点数,默认值0.0。
  7. boolean:布尔型,1位,只有 true 和 false,默认值 false。
  8. char:字符型,单一的 16 位 Unicode 字符,默认值'u0000'。

引用数据类型:对象,数组都是引用数据类型,引用数据类型指向一个对象,指向对象的变量是引用变量。

变量的作用范围,类变量、实例变量、局部变量的区别 ​

  1. 变量的作用域即作用范围,用一对大括号表示语句块的范围,在该作用域创建的变量,直到大括号关闭前都可以使用。
  2. 类变量也称静态变量,指被 static 修饰的成员变量,运行时 JVM 只为静态变量分配一次内存,在类的内部,可以在任何方法中直接访问静态变量;在其它类中,可以通过类名访问该类中的静态变量;静态变量可以被类的所有实例共享。
  3. 实例变量,指没有被 static 修饰的成员变量,每创建一个类的实例 JVM 就会为实例变量分配一次内存;在类的内部,可以在非静态方法中直接访问实例变量;在本类的静态方法或其他类中则需要通过类的实例对象进行访问。
  4. 局部变量,指在方法、形参、代码块中定义的变量,这种变量从初始化完成后开始生效,随着方法或代码块的结束而消亡,他们都被存储在方法的栈内存中。

面向对象的三大特征是什么 ​

封装、继承和多态

  1. 封装:封装就是隐藏对象的属性和实现细节,仅对外公开接口;封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口以特定的访问权限来使用类的对象。

  2. 继承:继承机制允许创建分等级层次的关系。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

  3. 多态:多态是同一个行为具有多个不同表现形式或形态的能力。是指一个类实例(对象)的相同方法在不同情形具有不同的表达形式。

多态的优点:消除类型之间的耦合关系,可替换性,可扩充性,接口性,灵活性和简化性。

多态存在的三个必要条件:继承,重写和父类引用指向子类对象。

简述封装的实现过程和实现的必要性 ​

  1. 封装的实现过程:
  2. 私有化成员变量,使用 private 关键字修饰。
  3. 提供公有的 get 和 set 方法,使用 public 修饰。
  4. 在外部直接调用 get 和 set 方法,即可对成员变量进行访问和修改。
  5. 实现的必要性:封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口以特定的访问权限来使用类的对象。

子类从父类那里继承了什么 ​

特征和行为即子类拥有父类非 private 的属性和方法 (包括构造方法) 并且可以直接调用。

简述多态的实现过程 ​

多态使用动态绑定机制:编译代码时,编译器只检查代码的语法是否有错;在运行代码时,执行器根据内存的真实情况去执行对应的代码;如果某个方法在子类中没有被重写,则执行父类的方法,反之则回去执行重写后的方法。

接口的构成和作用 ​

接口中的包含:

  1. 变量:接口中的变量全是用 static final 修饰的常量。
  2. 方法:接口中的方法全是默认使用 public abstract 修饰的方法,即空实现的抽象方法。

接口的作用:

  1. 统一访问:在接口中定义好的方法名或者变量名,类实现接口后,进行方法的实现,这样可以统一不同类实现相同方法时的方法名。
  2. 多重继承:可以通过实现多种接口实现多重继承。

final 的用法有哪些 ​

  1. 修饰变量:final 修饰的变量只能在定义时,进行一次赋值操作,并且在后续的使用中不可以改变它的值。
  2. 修饰方法:final 修饰的方法不能被覆盖。
  3. 修饰类:final 修饰的类无法被继承。

static 的用法有哪些 ​

  1. 修饰成员变量:被 static 修饰的成员变量叫静态成员变量或类变量;静态成员变量在内存中只有一份拷贝,JVM 只为静态成员变量分配一次内存,在加载类的过程中完成静态成员变量的内存分配,可以用类名直接访问,所有的实例对象共用一个静态变量。
  2. 修饰方法:被 static 修饰的方法叫做静态方法;静态方法可以直接通过类名调用,任何实例都可以调用,因此静态方法中不能用 this 和 super 关键字,不能直接访问所属类的实例变量和实例方法(不带 static 修饰的成员变量和方法),只能访问所属类的静态成员变量和静态方法。
  3. 修饰代码块:被 static 修饰的代码块叫静态代码块;静态代码块可以有多个,位置任意,它不在任何的方法体内,JVM 加载类时会执行这些静态代码块,如果 static 代码块有多个,JVM 将按照它们在类中出现的先后顺序执行它们,每个代码块只会被执行一次。

事件三要素是什么 ​

  1. 事件:事件封装了组件上发生的事情,比如按钮单击、按钮松开等。
  2. 事件源:即事件发生的场所,就是指各种组件,如按钮等。
  3. 事件监听器:负责监听事件源上发生的特定类型的事件,当事件到来时还必须负责处理相应的事件。

== 和 equals 的区别是什么 ​

  1. 基本数据类型只能使用 ==,这里的 == 比较的是两个基本类型的值。
  2. 对象:
  3. == 比较的是地址。
  4. equals 对于没有重写 equals 方法的类比较的是地址。
  5. equals 对于重写 equals 方法的类(如 String)则比较的是值。

简述 String 和 StringBuilder 定义变量的方式和内存模型 ​

  1. String:字符串常量,定义后字符串的长度不可变。
  2. StringBuilder:字符串变量,定义后字符串的长度可以改变。
  3. String 内存模型:底层用于存放字符的数组被声明为 final,因此只能赋值一次,不可再改变;定义字符串未使用 new 关键字时,会将定义的变量指向常量池中的字符串常量;使用new 关键字时,会在堆区中创建一个 String 的实例对象并在常量池创建对应的字符串常量,堆区的实例对象则会指向常量池中的字符串常量,而定义的变量则指向堆区的实例对象;使用 + 操作时,会额外创建 StringBuilder 变量指向新的字符串,并将 StringBuilder 变量转换为 String 重新赋值给字符串变量;重新赋值时都会生成新的 String 对象,然后把新的 String 对象赋值给原本的 String 引用。
  4. StringBuilder 内存模型:底层 StringBuilder 被当作是一个字符序列的变长数组,但不会保证线程同步;使用 StringBuilder 类时,每次都会对 StringBuilder 对象本身进行操作。

简述构造方法的几种形式 ​

  1. 无参构造方法:不带入参数的构造方法叫做无参构造方法。
  2. 有参构造方法:带入参数的构造方法叫做有参构造方法。
  3. 默认构造方法:即编译器自动创建的构造方法,默认的构造方法是空参空实现。

数据流、字符流、字节流的概念 ​

  1. 数据流:数据在内存和硬盘之间来回流动,所以叫做数据流;数据流是二进制存储的,对于二进制的数据流,如果8位一分割,就形成了字节流;如果按照字符编码格式去分割,就形成了字符流。

  2. 字符流:专门用于字符形式的读取和写入;以字符为单位对数据进行操作,在读的时候,将二进制数据转换为字符,在写的时候,将字符转换为二进制数据。类:Reader 和 Writer;标准流:FileReader 和 FileWriter ;缓冲流:BufferedReader 和 BufferedWriter。

  3. 字节流:以8位为单位,对二进制数据进行操作时对数据不进行转换;类:InputStream 和 OutputStream;标准流:FileInputStream 和 FileOutputStream;缓冲流:BufferInputStream 和 BufferOutputStream。

读写一个文本文件过程 ​

  1. 创建源:使用 File 类,获取文件的对象。
  2. 选择流:选择字节流或字符流;再选择标准流或缓冲流;创建流的对象。
  3. 读写操作:调用流的对象中读写操作方法,进行读写文件;缓冲流在写入时需要将缓冲区的再次进行写入。
  4. 释放资源:释放读写流对象的关闭操作,对文件进行关闭,防止之后无法打开。

File 类的作用是什么 ​

File 类是 Java 中代表文件本身的对象,符合 Java 中的万物皆对象原则。File 类主要用来获取和处理文件相关的信息,File 不具有从文件中读取信息和向文件中写入信息的功能,它仅用来描述文件本身的属性。

简述三种集合各自的特点,并列举有哪些类 ​

  1. List 集合:List 集合是按照顺序存放数据,允许数据存在重复。

包含 ArrayList 和 LinkList 类:

  1. ArrayList:是实现了基于动态数组的数据结构。

  2. LinkList:是实现了基于链表的数据结构。

  3. Set 集合:Set 集合是不允许出现重复元素,相同元素只会存放一个,Set 中没有角标,比较的是元素的 hashCode。

包含 TreeSet 、HashSet 和 LinkedHashSet 类:

  1. TreeSet:底层是红黑树的数据结构,有自己的排序,当存放的是对象时,排序对象要实现比较器接口 Comparable;

  2. HashSet:底层是 HashMap ,HashMap 中插入数据时的顺序和输出数据时的顺序无关。

  3. LinkedHashSet:去掉重复元素,插入数据的顺序与输出数据的顺序相同。

  4. Map 集合:Map 集合是一个键值对,存储的内容是键值对(key - value)映射。

包含 HashMap、Hashtable、LinkedHashMap 和 TreeMap:

  1. HashMap:是最常用的 Map,它根据键的 hashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap 最多只允许一条记录的键为 null,HashMap 不支持线程同步。
  2. Hashtable:与 HashMap 类似,不同的是,他不允许记录的键或值为空,并且支持线程同步,不过写入时会 HashMap 较慢。
  3. LinkedHashMap:保存了插入时的顺序,使用迭代器(Iterator)遍历时,会按照插入顺序输出,具有 HashMap 的全部特征,遍历时会比 HashMap 慢。
  4. TreeMap:能够把它保存的数据根据键进行排序,默认按照 key 升序排列,也可以指定排序的比较器,使用迭代器(Iterator)便利 TreeMap 时,得到的序列是排过序的,TreeMap 的键值都不可为空。

Java 类加载过程 ​

JVM 执行时,遇到一个新的类会去内存的堆区中寻找 class 的信息,如果找到则直接用;如果没有找到则会将字节码文件加载到堆区。

  1. 将父类所有的静态内容加载到静态方法区。
  2. 执行父类静态代码块的内容。
  3. 对所有父类静态变量进行默认初始化。
  4. 对所有父类静态变量进行显式初始化(赋值)。

2 和 3 谁写在前面先执行谁,4 跟在 3 后面执行。

  1. 将本类的所有静态内容加载到静态方法区。
  2. 执行本类的静态代码块的内容。
  3. 对所有本类静态变量进行默认初始化。
  4. 对所有本类静态变量进行显式初始化(赋值)。

5 和 6 谁写在前面先执行谁,7 跟在 6 后面执行。

  1. 将父类中所有非静态内容块加载到非静态方法区。
  2. 类的加载完成。

静态方法和非静态方法属于被动调用,只有调用时才会执行。

Java 对象的创建过程 ​

创建对象时,首先加载对应的类。

  1. new 一个对象时,在堆内容中开辟一块空间。
  2. 给开辟的空间分配一个地址。
  3. 把对象的所有非静态成员加载到所开辟的空间下。
  4. 所有的非静态成员加载完成之后,对所有非静态成员变量进行默认初始化。
  5. 所有非静态成员变量默认初始化完成之后,调用构造函数。
  6. 如果构造函数第一句是 super 则创建父类对象并调用父类对应的构造函数。
  7. 如果构造函数第一句是 this 则调用 this 对应的构造函数。
  8. 在整个构造函数执行完后,把空间分配的地址赋给引用对象。
  9. 对象的创建完成。

普通类和抽象类、内部类的区别 ​

  1. 普通类:与文件名相同并使用 class 修饰的类叫做普通类;类是 Java 中最基础的元素,可以用来生成对象,类中的方法不能有抽象方法,作为父类时,不强制要求子类必须重写父类的方法,可以被 final 修饰,代表不能继承该类。
  2. 抽象类:使用 abstract 修饰的类叫做抽象类;拥有抽象方法的类,必须定义成抽象类,抽象类可以没有抽象方法,抽象类不能实例化即不可以生成对象,作为父类时,如果子类不是抽象类,则要求子类一定要实现父类中的抽象方法,反之则不用,不能被 final 修饰。
  3. 内部类:在一个类内部定义的类叫做内部类;它可以直接访问和引用他的外部类的所有变量和方法,与外部类相比,内部类可以声明为 private 或 protected。

Released under the MIT License.