JAVA SE八股(1)

72 阅读10分钟

JAVA SE

Java特点

  1. 面向对象
  2. 平台无关
  3. 支持多线程
  4. 编译与解释并行

JVM、JDK、JRE

JVM: Java虚拟机,负责将Java字节码转换成特定平台的机器码并执行

JRE:Java运行时环境,包含运行Java程序所需的库,以及Java虚拟机

JDK:Java SDK,包含JRE以及编译器(javac)、Java文档生成工具(Javadoc)、Java调试器等开发工具。为开发者提供开发、编译、调试Java程序的一整套环境三分恶面渣逆袭:JDK、JRE、JVM关系

跨平台性

指Java语言编写的程序,一次编译后,可以在多个系统平台上运行。

因为Java程序是通过JVM在系统平台上运行的,只要该系统可以安装相应的JVM,该系统就可以运行Java程序

字节码

Java程序经过编译之类产生的.class文件,字节码能够被虚拟机识别,从而实现Java程序的跨平台性

JAVA程序运行流程:

  • 编译:将源码编译成虚拟机可以识别理解的字节码(.class)
  • 解释:虚拟机执行Java字节码,将字节码翻译成机器码
  • 执行:对应的机器执行二进制机器码
Java程序执行过程

数据类型

  1. 基本数据类型
  • 数值型
    • 整数类型(byte、short、int、long)
    • 浮点类型(float、double)
  • 字符型(char)
  • 布尔型(boolean)
数据类型默认值大小
booleanfalse1比特
char'\u0000'2字节
byte01字节
short02字节
int04字节
long0L8字节
float0.0f4字节
double0.08字节
  1. 引用数据类型
    • 类 class
    • 接口 interface
    • 数组 []

类型转换

自动类型转换:把数范围小的数值或变量直接赋给另一个数范围大的变量

强制类型转换:自动类型转换反过来,会丢失精度

Java自动类型转换方向

自动拆箱/装箱

装箱和拆箱

&和&&有什么区别

&:逻辑与,两边都要计算

&&:短路与,若左边为false,则右边的表达式会直接短路掉,不会进行运算

tips: |||也是如此

break、continue、return的区别及作用

  • break跳出整个循环
  • continue跳出这一次循环
  • return程序返回

面向对象VS面向过程

  • 面向过程:分析解决问题所需的步骤,然后用函数实现,使用的时候再一个一个的调用就可以
  • 面向对象:把构成问题的事务分解成各个对象,建立对象是为了描述整个问题的过程所发生的行为,目的是复用代码

面向对象特性

二哥的 Java 进阶之路
  • 封装:把一个对象的属性私有化,同时提供一些可以被外界访问的方法

  • 继承:允许一个类继承现有类的属性和方法。提高代码复用性

  • 多态:允许不同类的对象对同一消息做出响应,但表现出不同的行为

    前置条件:

    • 子类继承父类
    • 子类重写父类的方法
    • 父类引用指向子类对象
//子类继承父类
class Wangxiaoer extends Wanger {
    public void write() { // 子类重写父类方法
        System.out.println("记住仇恨,表明我们要奋发图强的心智");
    }

    public static void main(String[] args) {
        // 父类引用指向子类对象
        Wanger wanger = new Wangxiaoer();
        wanger.write();
    }
}

class Wanger {
    public void write() {
        System.out.println("勿忘国耻");
    }
}

bigsai:封装继承多态

重载重写区别?

重载:一个类中有多个名字相同但是参数个数不同的方法

  • 发生在一个类
  • 同名方法有不同参数(参数类型,个数不同或者都不同)

重写:父类具有和子类一样的方法,用于提供父类已经声明的方法的特殊实现

  • 发生在父类和子类之间
  • 子类和父类的返回类型、方法名、参数列表相同
  • 不能比父类的方法声明更多的异常

访问修饰符

访问修饰符和可见性

抽象类和接口区别(is-a vs has-a)

  • 一个类只能继承一个抽象类,但可以实现多个接口
  • 抽象类可以有方法体的方法,但接口没有(Java8以前)
  • 接口中的成员变量隐式为static final,但抽象类不是
  • 接口是隐式抽象,声明时没有必要使用abstract关键字
  • 接口中方法也是隐式抽象的,同样不需要。。。
  • 接口中的方法都是隐式public

Java 抽象类和接口的区别,看这一篇就够了,全面解析 | 二哥的Java进阶之路 (javabetter.cn)

成员变量和局部变量的区别?

  1. 成员变量属于类,能被访问控制修饰符修饰;局部变量属于方法中定义的变量或方法参数
  2. 成员变量如果被static修饰,就属于类,没有则属于实例;
  3. 若局部变量为为基本数据类型,则存于栈内存;若为引用类型,则存于指向堆内存对象的引用或者是指向常量池中的地址
  4. 成员变量随对象的创建而存在,局部变量随方法的调用而自动消失
  5. 成员变量会被赋予初值,而局部变量不会

静态变量和实例变量区别?

  • 静态变量:被static修饰的变量,属于类,不属于类中的任何一个对象,静态变量在内存中只有一个副本
  • 实例变量:依存于实例,必须先创建对象然后通过对象才能访问

类似

  • 静态方法:静态方法里不能访问类的非静态成员变量和方法
  • 实例方法:。。。,可以访问类的所有成员变量和方法

final关键字

  1. 修饰类时不能被继承
  2. 修饰方法时,不能被重写
  3. 修饰变量时,一旦初始化就不能修改
    • 基本数据类型数值初始化后不能更改
    • 引用类型变量,初始化后不能让其指向另一个对象,但是引用指向的对象内容可以变

==和equals的区别

都用于比较对象

  1. ==:用于比较两个对象的引用,即它们是否指向同一个对象实例

    对于基本数据类型,==比较的是值

  2. euqals():用于比较两个对象的内容是否相等。默认equals()方法和==相同,即比较对象引用

但是equals()方法经常被重写,如String类中,用于比较两个字符串的字符内容是否完全一样

String a = new String("hh");
String b = new String("hh");

// 使用 == 比较
System.out.println(a == b); // 输出 false,因为 a 和 b 引用不同的对象

// 使用 equals() 比较
System.out.println(a.equals(b)); // 输出 true,因为 a 和 b 的内容相同

hashCode和equals?

hashCode()用于获取哈希码,返回一个int整数,定义在Object类中,是一个本地方法。

哈希码由对象的内存地址或者对象属性计算出来,是int类型且不会重复,一般用作键值对的键

重写equals()方法必须重写hashCode()方法?

  1. 维护一致性
  2. 基于哈希的集合类通过对象的哈希码存储在不同的中,查找对象时通过哈希码确定在哪个桶中搜索,然后通过equals()方法在桶中找到正确的对象
  3. 若重写equals而不重写hashCode,则被认为是相等对象可能会有不同的哈希码

为什么hashCode相同,对象也不一定相等?

哈希码通过哈希函数将对象映射成一个整数值

目的是在哈希表中快速定位对象的存储位置

哈希函数将一个较大的输入域映射到一个较小的输出域,不同输入值可能会产生相同的输出值(哈希冲突)

所以还得比较equals方法

if (p.hash == hash &&
    ((k = p.key) == key || (key != null && key.equals(k))))
    e = p;

值传递

当一个对象作为参数传递到方法中,参数的值就是该对象的引用,引用的值是对象在堆中的地址

传递对象可以理解为传递变量存储的对象地址

三分恶面渣逆袭:Java引用数据值传递示意图

深浅拷贝

  • 浅拷贝:仅拷贝值,包括基本数据类型变量的值,和引用数据类型变量的地址值,不拷贝引用类型变量指向的堆中的对象

  • 深拷贝:完全拷贝一份对象,更安全

    浅拷贝和深拷贝示意图

浅拷贝实现?

通过Object类中的clone()方法

深拷贝实现?

  • 重写克隆方法
  • 序列化

创建对象方式

Java创建对象的四种方式


String

String是一个类,是引用数据类型。

且被final修饰,不可变不能被继承

String 和 StringBuilder、StringBuffer 的区别?

String不可变,用的多,每次修改都会产生新对象

StringBuilder常用于大量字符串连接,基于底层字符数组,不会产生新的String对象

StringBuffer线程安全,域StringBuilder类似

String str1 = new String("abc") 和 String str2 = "abc" 的区别?

三分恶面渣逆袭:堆与常量池中的String


Integer

对于第一对是相等的,会自动装箱,Integer.valueOf()来创建对象,该方法会缓存-128到127之间的Integer对象,因此,a和·b实际上引用了常量池中相同的Integer对象

Integer a = 127;
Integer b = 127;

String转Integer

  • Integer.parseInt(String s)
  • Integer.valueOf(String s)

这两种方法最终都会调用Integer类内的parseInt(String s,int radix)方法


异常处理

异常处理

  • 遇到异常不能进行具体处理,而是继续抛给调用者

    throws用在方法上,后面跟的异常类,可以有多个

    throw用在方法内,后面跟的异常对象

  • try catch捕获异常

    finally语句块必然被执行

IO

按数据流分为

  • 输入流:从源(文件、网络)读取数据到程序
  • 输出流:将数据从程序写出到目的地(文件、网络、控制台)

按处理数据单位分为

  • 字节流:以字节为单位读写数据,主要处理二进制数据,如音频、图像文件
  • 字符流:以字符为单位进行读写,主要处理文本数据

按功能分为

  • 节点流:直接与数据源或目的地相连,如 FileInputStream、FileOutputStream。
  • 处理流:对一个已存在的流进行包装,如缓冲流 BufferedInputStream、BufferedOutputStream。
  • 管道流:用于线程之间的数据传输,如 PipedInputStream、PipedOutputStream。

BIO、NIO、AIO区别

  • BIO:阻塞式I/O模型,线程在执行I/O操作时被阻塞,无法处理其他任务,适用于连接较少的场景

  • NIO:非阻塞I/O模型,线程在等待I/O时可执行其他任务,通过Selector监控多个Channel上的事件,适用于连接数多但连接时长短的场景

  • AIO:异步I/O模型,线程发起I/O请求后立即返回,当I/O操作完成时通过回调函数通知线程,

    用于连接数多且连接时长长的场景

二哥的 Java 进阶之路:IO 分类

BIO简介

传统IO,基于字节流或字符流进行文件读写

对于每个连接,都需要创建一个独立的线程来处理读写

NIO简介

主要用于网络编程,服务器可以用一个线程处理多个客户端连接,通过 Selector 监听多个 Channel 来实现多路复用三分恶面渣逆袭:NIO

AIO简介

使用I/O操作进行异步进行,线程发起一个读写操作后不必等待完成,可以进行其他任务,当读写操作真正完成,线程会被异步通知


反射

编译后生成字节码文件,JVM进行类加载的时候,会加载字节码文件,将类型相关的所有信息加载进方法区,反射就是去获取这些信息,然后操作

装来动态加载类并创建对象

String className = "java.util.Date";
Class<?> cls = Class.forName(className);
Object obj = cls.newInstance();
System.out.println(obj.getClass().getName());

访问字段和方法:

// 加载并实例化类
Class<?> cls = Class.forName("java.util.Date");
Object obj = cls.newInstance();

// 获取并调用方法
Method method = cls.getMethod("getTime");
Object result = method.invoke(obj);
System.out.println("Time: " + result);

// 访问字段
Field field = cls.getDeclaredField("fastTime");
field.setAccessible(true); // 对于私有字段需要这样做
System.out.println("fastTime: " + field.getLong(obj));

JDK1.8新特性(太新了)

JDK1.8主要新特性