Java 语言的特点
- 面对对象:Java 中所有的数据和方法都封装在对象中
- 跨平台性:Java 通过 Java 虚拟机,可以在不同的操作系统上运行相同的程序
- 自动内存管理:Java 提供垃圾回收机制,不需要手动管理内存
- 强类型语言:Java 编译器在编译时会进行类型检查
- 多线程支持:Java 语言支持多线程
- 异常处理:Java 使用异常处理机制来处理运行时错误
JVM JDK JRE
- JVM:Java 虚拟机,使 Java 程序在不同平台运行,JVM 将 Java 程序编译后的字节码文件,然后解释成机器码执行。
- JDK:Java 开发工具包,包括 JRE、开发工具和 Java 类库
- JRE:JRE 是 Java 运行时环境,包括 JVM 和基本类库,没有开发工具
什么是跨平台性?原理是什么?
- 跨平台性:程序一次编译,不需要修改,就可以在不同的系统运行
- 原理:JVM 将 Java 程序编译后的字节码文件解释成机器码执行,JVM 针对不同的系统有不同的实现
什么是字节码?采用字节码的好处是什么?
- 字节码是 Java 程序编译后生成的.class 文件,在 JVM 上运行
- 好处:
- 实现 Java 程序的平台无关性
- 生成字节码文件的编译过程比直接解释执行速度快
- 字节码相比于机器码,更容易维护和调试
Java 和 C++ 的区别?
- 面对对象:Java 是面对对象的语言;C++ 支持面对对象,也有面对过程编程
- 内存管理:Java 使用垃圾回收机制自动管理内存;C++ 需要手动管理内存
- 跨平台性:Java 具有跨平台性;C++ 移植性差
- 异常处理:Java 使用异常处理机制,强制处理异常情况;C++ 不强制
注释?
- 单行注释
- 多行注释
- 文档注释
关键字
- 基本类型:int; long; short; byte; char; float; double; boolean
- 程序控制:break; contine; return; instanceof; default
- 访问控制:private; protected; public
- 类、方法:abstract; class; extends; final; implements; interface; native; new; static; synchronized; transient; volatile
- 错误处理:try-catch; throw; throws
- 包相关:import; package
- 变量引用:super; this; void
关键字 instanceof
- 检验是否是类对象
类型转换
- 子类到父类的转换(向上转型):通常用来实现多态性,通过父类引用来调用子类对象的方法,实现方法的动态绑定
- 父类到子类的转换(向下转型):强制类型转换,可能出现
ClassCastException
异常,需要使用instanceof
关键字
关键字 this 和 super
- this: 引用当前对象
- super:引用父类对象
关键字 final finally finalize?
- final:用来修饰不可变的实体,例如类、方法、变量等
- finally:用于定义在异常处理中,无论是否发生异常,finall 中的代码一定会执行;通常用于释放资源
- finalize:Object 类的方法,用于对象被垃圾回收前进行释放资源;
但由于 JVM 的垃圾回收是不确定的。finalize 不一定能有效回收对象资源;
推荐使用try-with-resource
方法
自增自减运算符
- 前缀:先加减,后返回值 ++i
- 后缀:先返回值,然后加减 i++
continue、break 和 return 区别?
- contine:跳出当前循环,进行下一次循环
- break:跳出整个循环体
- return:结束方法,并返回值
变量按照数据类型的分类?
- 基本数据类型
- 数值型:byte; int; short; long
- 浮点型:float; double
- 字符型:char
- 布尔型:boolean
- 引用数据类型
- 类:class
- 接口:interface
- 数组:array
讲讲数组的声明?
要使用 Java 数组,分为两个步骤:声明数组和分配内存
- 数组声明后在栈内存中保存数组的名称
- 然后在堆内存中分配数组所需要的内存
数据类型 数组名[] = null; //声明一维数组
数据名 = new 数据类型[长度]; //分配内存给数组
int array[] = null;
array = new int[5];
变量按照声明位置的分类?
- 类变量:定义在类中,使用 static 修饰,类变量在内存中只有一份
- 实例变量:定义在类中,属于类对象
- 局部变量:定义在方法或代码块中
成员变量和局部变量?
- 成员变量
- 也称实例变量
- 定义在类中方法体外,作用域是整个类,存储在堆内存中
- 有默认值
- 可以用访问权限控制修饰符修饰
- 局部变量
- 定义在方法或代码块中,作用域是所在的方法或代码块中,存储在栈内存中
- 必须显式赋值
- 只能在方法或代码块中使用,不需要访问修饰符
静态变量?
- 也称类变量
- 是指在类中使用 static 关键字定义的变量,属于类,不属于类的任何一个对象
- 在类加载的时候就被初始化了,存储在静态存储区,不在堆内存中
- 在整个程序执行期间只有一份拷贝,被所有实例对象共享使用
字符型常量和字符串常量的区别?
- 数据类型不同:
- 字符型常量是 char 类型,表示单个字符
- 字符串常量是 String 类型,表示多个字符组成的字符串
- 表示形式不同:
- 字符型常量用单引号引起来
- 字符串常量是双引号引来的 0 个或者若干字符
- 占内存空间不同:
- 字符型常量占 2 个字节
- 字符串常量占若干个字节
- 比较方式不同:
- 字符型常量可以使用==运算符进行比较,比较两个字符的 Unicode 编码
- 字符串常量使用则是比较两个字符串对象的引用地址,通常使用 equal() 方法比较两个字符串的内容是否相同
方法的返回值?方法的类型?
- 返回值:方法体执行后产生的结果
- 方法的类型:按照是否有形参及返回值可以组合为四种
静态方法为什么不能调用非静态成员?
- 静态方法属于类,在类加载的时候就会初始化,可以直接通过类名直接访问
- 非静态成员属于实例对象,只有在对象实例化后才存在,需要通过类的对象去访问
- 所以,非静态成员不存在时,静态方法去内存调用,属于非法操作
静态方法和实例方法?
- 静态方法属于类,通常使用类名.方法名方式访问
- 实例方法属于对象,通过对象.方法名访问
- 静态方法,只能调用静态成员,不能访问实例方法
重写和重载?
- 重写:子类继承父类,重新实现父类的方法,方法名、参数列表和返回值必须和父类的方法相同
- 重载:重载就是方法名称相同,但参数的类型和参数的个数不同。通过传递参数的个数和类型的不同可以完成不同功能的方法调用
基本类型和包装类型?
- 基本类型: Java 中最基本的数据类型,包括 boolean,byte,int,long,short,float,double,char
- 包装类型:将基本类型包装成一个对象的类,包括 Boolean,Byte,Integer,Long,Short,Float,Double,Character
基本类型和包装类型的不同?
- 包装类型是引用类型,需要使用 new 创建对象,且包装类型不可变;而基本类型是值类型,不需要创建对象
- 基本类型有默认值,成员变量的包装类型不赋值就是 null
- 在泛型、反射中,只能使用包装类型,不能使用基本类型
自动装箱与拆箱?
- 自动装箱:将基本类型值转换为对应的包装类型实例 valueOf()
Integer i = 10; //等价于 Integer i = Integer.valueof(i);
- 自动拆箱:将包装类型实例转换为对应的基本类型值 intValue()
int n = i;//等价于 int n = i.intValue();
包装类型的缓存机制?
- 在类初始化时,提前为常见范围内的数创建了一个缓存数组
- 例如 Integer 类型,Java 会在缓存数组中创建 -128~127 的所有整数的对象
如果通过 valueOf() 方法传入这个范围内的整数,就会直接返回缓存中的对象,而不是创建一个新的对象
这样就避免了频繁创建和销毁对象,提高了程序的性能 - 对于超出缓存范围的数值,valueOf() 方法依然会创建新的对象
为什么浮点数会有精度丢失的风险?
- 浮点数在计算机中是通过二进制小数来表示的
- 但有一些小数无法准确用有限个二进制位来表示,这种情况就会出现精度丢失的问题
如何解决浮点数运算的精度丢失?
- 使用 BigDecimal 类
- 在比较浮点数是否相等时,避免直接使用 “==” 运算符
超过 long 整型的数据如何表示?
- 使用 BigInteger 类
对象实例和对象引用有什么不同?
- 对象实例:是一个具体的实体,在内存中有对应的存储空间。对象实例通常是根据类来创建的,一个类可以 new 关键字创建多个对象实例
- 对象引用:是一个指针,指向内存中实际的对象实例。存储的是对象在内存中地址
- 对象实例的声明周期由 JVM 垃圾回收机制管理,对象引用声明周期由程序控制
对象的相等和引用相等的区别?
- 对象的相等:内存中存放的内容是否相等
- 引用相等:指向的内存地址是否相等
构造方法有哪些特点?是否可以被 override?
构造方法是一种特殊的方法,用于创建和初始化对象,具有以下特点:
- 构造方法的名字必须和类名相同
- 没有返回值类型
- 如果没有显示定义构造方法,Java 会默认提供一个无参的构造方法
- 构造方法在对象被创建的时候自动调用,不能手动调用
- 不能被重写,如果子类需要增加属性或方法,可以使用 super() 来调用父类的构造方法,在子类的构造方法中添加新的代码
JavaBean?
- JavaBean 是一种特殊的 Java 类,遵循一定的规范,可以被多种工具和框架使用
- JavaBean 主要用于简化 Java 对象的创建和管理,同时提供标准化的方式来访问 Java 对象的属性
JavaBean 要求
- 所有的属性都是私有的
- 有一个无参的构造方法
- 有 get 和 set 方法
深拷贝 浅拷贝 引用拷贝?
-
深拷贝:
将被复制对象完全复制一份,即在内存中重新开辟一个地址存放新对象,并且新对象和原对象没有任何关系
修改新对象不会影响原对象 -
浅拷贝
拷贝对象和原对象的引用类型引用同一个对象,即在内存中开辟新空间存储一个新对象,并且这个新对象与原对象共享内存中的属性值
即修改一个对象的属性值,另一个对象的属性值也会发生改变 -
引用拷贝
将被复制对象的引用地址直接复制给一个新的对象,指向同一个内存空间
修改其中一个对象的属性值,另一个对象的属性值也会发生改变
Object 类的方法?
- getClass():返回当前运行时对象的 Class 对象
- hashCode():返回对象的哈希码
- equals():比较对象的内存地址是否相等
- clone():创建并返回当前对象的一份拷贝
- toString():返回对象的字符串表示
- notify():唤醒一个在对象监视器上等待的线程
- notifyAll():唤醒对象监视器上等待的所有线程
- wait():暂停线程的执行
- finalize():实例被垃圾回收器回收时触发的操作
==和 equals() 的区别?
- ==运算符:用于比较两个对象引用是否指向同一个对象
如果两个对象的物理地址相同,则相同 - equals() :用于比较两个对象的内容是否相等
默认情况下,比较的是两个对象的物理地址,但可以通过重写来比较两个对象的内容是否相同
在重写 equals 方法时,通常还需要重写 hashCode() 方法
接口和抽象类
接口的方法不可以有实现,并且是绝对的抽象方法。抽象类可以有实例方法用来实现默认行为
接口用来定义契约行为,也可作为两个系统间的契约进行交互
而抽象类主要用来为子类定义默认行为,也就是说所有的继承子类都需要运行相同的功能