面经-JAVA基础
JAVA基础
equals和==的区别:
对于基本数据类型,int,double等,“==”号判断两者的数值是否相等,而对于字符串(引用数据类型),如“Hello!”对象,“==”号判断的是两者的指向字符串地址是否相同,如要判断两个字符串其中的每一个字符是否相同,可以用equals()方法。
注意,如果字符串在创建时没有选择重建字符串,那么两个对象指向的字符串地址是一致的,但是如果修改其中一个对象的值,该对象指向的字符串地址会改变,另外一个对象仍旧指向原来的字符串地址没有改变,这是在底层的java逻辑设置中的(String)。但是一开始就是重建两个字符串则不存在这样的问题,就是说即使两个对象创建的字符串相同,这两个对象指向的字符串地址也不一致。
1 | package practiceClass.a0512; |
1 | public class b01_test { |
类型封装
iterger是int的对象类型封装,因为java是面向对象编程的。
重写和重载
方法的重写
Override
- 当父类的方法不能满足子类现在的需求时,需要进行方法的重写
- 格式是在重写后的方法上面加上 ‘@Override’ ,该标志是用来校验子类重写的方法格式是否是正确的,当然不加也可以,但最好加上
- 子类的重写方法权限最好用父类的保持一致,当然子类的权限可以大于等于父类
方法的重载
Overload
重载用于提供同一操作的不同实现,如下面都是函数相加,虽然变量数不同,却都可以用同一个函数名来表示
1 | public class b02_overload { |
1 | 3 |
背诵总结
Java中的重写和重载是实现多态的两种不同方式。
方法的重载是编译时多态,指的是在同一个类中,可以存在有相同名称的多个方法,它们的参数列表不同(参数的类型、个数、顺序),也可以有不同的返回类型和访问修饰符。
方法的重写是运行时多态,指的是在子类中重新定义父类中已经定义的方法,子类中的方法名、参数列表和返回类型都必须相同。重写的方法的访问级别不能低于被重写的父类方法,虚拟机在运行时根据对象的实际类型来确定调用哪个方法。
总结来说,重载关注的是方法的多样性,允许同一个类中存在多个同名方法;而重写关注的是方法的一致性,允许子类提供特定于其自己的行为实现。
单与运算符&和双与运算符&&的区别
在 Java 中,&
和 &&
都是逻辑运算符,但它们的作用和使用场景有所不同:
&
(按位与运算符):- 用途:
&
是按位与运算符,通常用于整数类型(如int
、long
)的按位操作。它逐位对两个操作数进行“与”运算。只有对应的位都是 1 时,结果才是 1,否则是 0。 - 逻辑操作:
&
也可以用于布尔值(boolean
)的逻辑运算,但它没有短路行为。 - 短路行为:
&
不具有短路行为,即它总是会对两个操作数都进行求值。
示例:
1
2
3int a = 5; // 0101
int b = 3; // 0011
int c = a & b; // 0001, 结果是 1对于布尔类型:
1
2
3boolean x = true;
boolean y = false;
boolean result = x & y; // 结果是 false无论
x
或y
的值如何,&
运算符都会对两个布尔值都进行求值。- 用途:
&&
(逻辑与运算符):- 用途:
&&
是逻辑与运算符,专门用于布尔值的逻辑运算。它在两边的操作数都是布尔值时返回一个布尔结果。 - 短路行为:
&&
具有短路行为。如果第一个操作数为false
,它就不会再计算第二个操作数,因为false &&
后面的任何值都不会影响结果。这种特性可以提高效率,避免不必要的计算。
示例:
1
2
3boolean x = true;
boolean y = false;
boolean result = x && y; // 结果是 false如果用于短路:
1
2
3boolean x = false;
boolean y = someMethod(); // someMethod() 可能会抛出异常
boolean result = x && y; // 由于 x 为 false,y 不会被求值,someMethod() 不会被调用,也就不会抛出异常- 用途:
总结:
&
是按位与运算符,通常用于整数类型的按位运算,或布尔类型的逻辑运算,但没有短路行为。&&
是逻辑与运算符,专门用于布尔值的逻辑运算,且具有短路行为。
因此,&&
在布尔逻辑中更常用,尤其在控制流语句(如if
语句)中,它能有效提高程序效率和防止潜在错误。
形参和实参
形参是定义通用方法时输入的形式参数,如Person p
而实参是在实际调用这个方法时输入的实际参数,如Student s、Teacher t
String,StringBuffer和StringBuilder
特性 | String | StringBuffer | StringBuilder |
---|---|---|---|
是否可变 | 不可变 | 可变 | 可变 |
变量是否跨线程 | 跨 | 跨 | 不跨 |
使用场景 | 字符串内容少量修改 | 多线程环境下同步修改 | 单线程环境下修改 |
因此,在实际开发中
- 如果字符串很少修改,直接使用不可变的String
- 如果在多线程环境下频繁操作字符串,可以选择StringBuffer
- 如果是单线程,用StringBuilder
变量可以跨线程我们叫线程不安全
当多个线程同时访问和修改同一个变量时,如果没有适当的同步机制来保证线程之间的顺序和互斥访问,这个变量就被认为是线程不安全的。这种情况会导致竞争条件(race condition),即多个线程在没有协调的情况下同时修改变量的值,最终导致不可预测的结果。
抽象类和接口的区别
抽象类
抽象类本质是一个类,它是在原有类的基础上,增加了抽象的能力,即可以定义抽象方法。正是因为它可以拥有抽象方法,所以即便有构造器(无参有参构造),也不能直接创建对象。
接口
接口则是完全抽象(所有的方法在接口中都没有实现)。(JDK8之后,接口中可以包含默认方法和静态方法)
区别
一个类只能继承一个抽象类;可以实现多个接口
抽象类中方法和字段可以是任何访问修饰符;接口中的方法默认都是public abstract,字段默认都是public static final
抽象类用于定义一个类的公共行为和状态,表示 是什么;接口用于定义一组行为规范,表示 *能做什么
java常见的异常类有哪些
区别
编译时异常:通常是由外部因素引发的异常(如文件I/O操作、数据库连接失败等) ,开发者无法完全预知这些问题,因此编译器强制要求进行处理。
运行时异常:一般是由开发者的编程错误或逻辑漏洞引发的,属于程序内部的问题,开发者理论上可以预知,可以在调试阶段发现处理。
处理方式
编译时异常:使用try-catch或者throws关键字声明抛出。
运行时异常:通常选择使用try-catch捕获处理或程序终止时由JVM抛出
常见的编译时异常:
SQLException:数据库访问出错。
FileNotFoundException :文件未找到。
ClassNotFoundException:无法找到指定类。
InterruptedException :线程在阻塞状态被打断。
常见的运行时异常:
ArithmeticException:数学运算错误,例如除以零。
ClassCastException:强制类型转换失败。
ArrayIndexOutofBoundsException:数组索引越界。
try-catch-finally
不带 return 的执行顺序
异常处理中,try、catch 、finally 的执行顺序:
- 如果 try 中没有异常,执行顺序为:try —> finally
- 如果 try 中有异常,执行顺序为:try —> catch —> finally
带 return 的执行顺序
- finally 中的代码总会执行
- 当 try、catch 中有 return 时,也会执行 finally。
- finally 中有 return 时,会直接在 finally 中退出,导致 try、catch 中的 return 失效
Java面向对象三大特性
Java面向对象编程的三大特性是封装、继承和多态:
- 封装:封装是将对象的属性(成员变量)和行为(成员方法)结合在一起,并隐藏内部的实现细节,只暴露出一个可以被外界访问的接口。
- 继承:允许一个类(子类)继承另一个类(父类)的属性和方法的机制。子类可以重用或者重写父类的方法,一个类只能直接继承一个父类。
- 多态:多态是指允许不同类的对象对同一消息做出响应,但具体的行为会根据对象的实际类型而有所不同。这通常通过方法重载和重写实现。(背下面)
Java多态
- 多态是指:创建对象时,使用父类型作为参数,接受所有的子类对象,使用该对象的方法时,其方法行为总是表现出子类方法的行为特征,而不是父类方法的行为特征,这就可能出现:相同类型的对象、调用同一个方法时呈现出多种不同的行为特征。
优势和劣势
优势
- 创建对象时,使用父类型作为参数,可以接受所有的子类对象,子类对象可以实现解耦合,便于扩展和维护。
1 | Person p = new Student(); // 当业务逻辑发生变化时,只需要将这里的Student改变即可 |
劣势
多态的父类方法定义往往不能面面俱到,而多态方法的定义往往是编译看左边,运行看右面。因此,我们如果想调用子类中的特有方法,而这种方法在多态中没有的话(不是用Override重写的方法),编译就会报错,为了解决这个问题,我们会对变量对象进行强转,将之前声明的父类对象强转为子类对象。
final关键字有什么作用
final
就是不可变的意思,可以修饰变量、方法和类。
- 修饰变量:
final
修饰 基本数据类型的变量,其数值一旦在初始化之后便不能更改, 称为常量;final
修饰 引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。虽然不能再指向其他对象,但是它指向的对象的内容是可变的
- 修饰方法:
final
修饰方法是明确禁止该方法在子类中被覆盖 - 修饰类:
final
修饰的类不可被继承,是最终类。