基础

发布时间 2023-05-29 16:34:28作者: 好记性不如烂笔头=>
1、Java 的异常体系
Java 中 Throwable 是所有异常和错误的超类,两个直接子类是 Error(错误)和 Exception(异
常):
1)Error 是程序无法处理的错误,由 JVM 产生和抛出,如 OOM、ThreadDeath 等。这些异常
发生时,JVM 一般会选择终止程序。
2)
Exception 是程序本身可以处理的异常,又分为运行时异常(RuntimeException)(也叫 Checked
Eception) 和 非 运 行 时 异 常 ( 不 检 查 异 常 Unchecked Exception) 。 运 行 时 异 常 有
NullPointerException\IndexOutOfBoundsException 等,这些异常一般是由程序逻辑错误引起
的,应尽可能避免。非运行时异常有 IOException\SQLException\FileNotFoundException 以及
由用户自定义的 Exception 异常等。
2、Java 中实现多态的机制是什么?
多态是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编
译时不确定,在运行期间才确定,一个引用变量到底会指向哪个类的实例。这样就可以不用
修改源程序,就可以让引用变量绑定到各种不同的类实现上。
Java 实现多态有三个必要条件:
继承、重定、向上转型,在多态中需要将子类的引用赋值给父类对象,只有这样该引用才能
够具备调用父类方法和子类的方法。
3、说说你对 Java 反射的理解
在运行状态中,对任意一个类,都能知道这个类的所有属性和方法,对任意一个对象,都能
调用它的任意一个方法和属性。这种能动态获取信息及动态调用对象方法的功能称为 java
语言的反射机制。
反射的作用:开发过程中,经常会遇到某个类的某个成员变量、方法或属性是私有的,或只
对系统应用开放,这里就可以利用 java 的反射机制通过反射来获取所需的私有成员或是方
法。
1) 获取类的 Class 对象实例 Class clz = Class.forName("com.zhenai.api.Apple");
2) 根 据 Class 对 象 实 例 获 取 Constructor 对 象
Constructor appConstructor =
clz.getConstructor();
3) 使 用 Constructor 对 象 的 newInstance 方 法 获 取 反 射 类 对 象 Object appleObj =
appConstructor.newInstance();
4) 获取方法的 Method 对象 Method setPriceMethod = clz.getMethod("setPrice", int.class);5) 利用 invoke 方法调用方法 setPriceMethod.invoke(appleObj, 14);
6) 通过 getFields()可以获取 Class 类的属性,但无法获取私有属性,而 getDeclaredFields()可
以获取到包括私有属性在内的所有属性。带有 Declared 修饰的方法可以反射到私有的方法,
没有 Declared 修饰的只能用来反射公有的方法,其他如 Annotation\Field\Constructor 也是如
此。
 
Java 中 String 的了解
1)String 类是 final 型,固 String 类不能被继承,它的成员方法也都默认为 final 方法。String
对象一旦创建就固定不变了,对 String 对象的任何改变都不影响到原对象,相关的任何改变
操作都会生成新的 String 对象。
2)String 类是通过 char 数组来保存字符串的,String 对 equals 方法进行了重定,比较的是
值相等。
String a = "test"; String b = "test"; String c = new String("test");
a、b 和字面上的 test 都是指向 JVM 字符串常量池中的"test"对象,他们指向同一个对象。而
new 关键字一定会产生一个对象 test,该对象存储在堆中。所以 new String("test")产生了两
个对象,保存在栈中的 c 和保存在堆中的 test。而在 java 中根本就不存在两个完全一模一样
的字符串对象,故在堆中的 test 应该是引用字符串常量池中的 test。
例:
String str1 = "abc"; //栈中开辟一块空间存放引用 str1,str1 指向池中 String 常量"abc"
String str2 = "def"; //栈中开辟一块空间存放引用 str2,str2 指向池中 String 常量"def"
String str3 = str1 + str2;//栈中开辟一块空间存放引用 str3
//str1+str2 通过 StringBuilder 的最后一步 toString()方法返回一个新的 String 对象"abcdef"
//会在堆中开辟一块空间存放此对象,引用str3指向堆中的(str1+str2)所返回的新String对象。
System.out.println(str3 == "abcdef");//返回 false
因为 str3 指向堆中的"abcdef"对象,而"abcdef"是字符池中的对象,所以结果为 false。JVM
对 String str="abc"对象放在常量池是在编译时做的,而 String str3=str1+str2 是在运行时才知
道的,new 对象也是在运行时才做的。
14、String 为什么要设计成不可变的?
1)字符串常量池需要 String 不可变。因为 String 设计成不可变,当创建一个 String 对象时,
若此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。
如果字符串变量允许必变,会导致各种逻辑错误,如改变一个对象会影响到另一个独立对象。
2)String 对象可以缓存 hashCode。字符串的不可变性保证了 hash 码的唯一性,因此可以缓
存 String 的 hashCode,这样不用每次去重新计算哈希码。在进行字符串比较时,可以直接比较 hashCode,提高了比较性能;
3)安全性。String 被许多 java 类用来当作参数,如 url 地址,文件 path 路径,反射机制所
需的 Strign 参数等,若 String 可变,将会引起各种安全隐患。