目录
1.1.5 3*0.1 == 0.3 将会返回什么? true 还是 false?
1.1.7 对equals()和hashCode()的理解?
1.1.8 final、finalize 和 finally 的不同之处?
1.1.9 String、StringBuffer与StringBuilder的区别?
1.1.10 this() & super()在构造方法中的区别?
1 Java基础:
1.1 语法基础:
1.1.1 封装:
封装定义:利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体。数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。用户无需知道对象内部的细节,但可以通过对象对外提供的接口来访问该对象。
个人理解:所谓封装其实就是对数据和对数据处理的处理操作进行不可见操作将内部细节尽可能的隐藏起来,将数据保护在内部。这也使得这些数据和操作都成为一体不可分割。封装使调用者无法得知内部数据、运算处理等信息。只能通过一些内部提供的对外接口来进行交互获取和提交数据。
封装优点:
- 减少耦合: 可以独立地开发、测试、优化、使用、理解和修改
- 减轻维护的负担: 可以更容易被程序员理解,并且在调试的时候可以不影响其他模块
- 有效地调节性能: 可以通过剖析确定哪些模块影响了系统的性能
- 提高软件的可重用性
- 降低了构建大型系统的风险: 即使整个系统不可用,但是这些独立的模块却有可能是可用的
![](https://img-blog.csdnimg.cn/897d0b76aa9b42c49faab6ded616bb03.png)
1.1.2 继承
继承关系就是类之间的IS-A关系,例如:Cat is a animal,Cat类继承与Ainmal类,Cat类会继承来自Animal类的所有非private字段的属性和方法【为什么不包括private???父类还不能有自己的秘密是吧[doge]】
来看下面一张debug图:
不是说employee不能继承来自父类的私有属性吗???这实例化employee确实有这俩属性啊?
那么该如何理解子类不能继承父类私有属性呢??? 其实这俩不是继承过来的,是通过super访问的来的(你得问老爸的小秘密才能告诉你嘛!!!)假如想通过this来访问这俩数据时,是查不到的。
所以综上所述,我们可以得知,父类的private属性是无法被继承到的,子类虽然有这个属性,但是是通过“询问”老父亲的来的,而不是继承来的!!!
public class demo {
public static void main(String[] args) {
Persion employee = new Employee(22,"卷王班长");
System.out.println(employee.getName());
}
}
class Employee extends Persion{
private int money;
public Employee() {
}
public Employee(int age, String name) {
super(age, name);
}
}
class Persion{
public int skill;
private int age;
private String name;
public Persion() {
}
public Persion(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
private void test(){
}
}
1.1.3 多态
通俗的讲,多态就是一个东西可以指示多种实际类型的现象
Java中多态分为编译时多态和运行时多态:
- 编译时多态主要指方法的重载
- 运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定
运行时多态有三个条件:
- 继承
- 覆盖(重写)
- 向上转型
下面是重写方法的例子,Human类型引用teacher类对象和worker类对象并调用working方法,调用的不是Human自身的方法打印”身而为人“,而是调用了teacher和worker内部重写的working方法
public class demo2 {
public static void main(String[] args) {
Human teacher = new Teacher();
Human worker = new Worker();
teacher.working();
worker.working();
}
}
class Teacher extends Human{
@Override
public void working() {
System.out.println("老师正在上课~");
}
}
class Worker extends Human{
@Override
public void working() {
System.out.println("工人正在作业~");
}
}
class Human{
public void working(){
System.out.println("身而为人");
}
}
1.1.4 a = a + b 与 a += b 的区别
+= 隐式的将加操作的结果类型强制转换为持有结果的类型。如果两个整型相加,如 byte、short 或者 int,首先会将它们提升到 int 类型,然后在执行加法操作。
+ 操作就只是上升类型等级(byte、short ->int ,float->double,int->long(如果赋值类型为long才会这样,否则默认是int)),然后直接赋值了
byte a = 127;
byte b = 127;
b = a + b; // error : cannot convert from int to byte
b += a; // ok
1.1.5 3*0.1 == 0.3 将会返回什么? true 还是 false?
返回false,浮点数精度无法精确表示出来,末尾还有小数位
1.1.6 能在 Switch 中使用 String 吗?
从 Java 7 开始,我们可以在 switch case 中使用字符串,内部实现在 switch 中使用字符串的 hash code。
1.1.7 对equals()和hashCode()的理解?
- 为什么在重写 equals 方法的时候需要重写 hashCode 方法?
因为有强制的规范指定需要同时重写 hashcode 与 equals 是方法,许多容器类,如 HashMap、HashSet 都依赖于 hashcode 与 equals 的规定。
- 有没有可能两个不相等的对象有相同的 hashcode?
有可能,两个不相等的对象可能会有相同的 hashcode 值(散列函数计算可能一样),这就是为什么在 HashMap 中会有冲突。
- 两个相同的对象会有不同的 hash code 吗?
不能,对象相同利用散列函数计算出来的结果是一样的
1.1.8 final、finalize 和 finally 的不同之处?
final: 修饰符,意味“最终”,修饰变量(初始化后不能改变值)、方法(不能被重写)、类(不能被继承,我们熟知的String就是一个final类)
finally: 用于异常,finally代码块内的语句在return之前一定会执行。
这就引出finally导致的特殊情况,
就如我们所知,return表示的是一个程序将结束,而finally又是try后必须执行的代码块,假如执行了try里面的return语句,就不符合规则了,所以在try语句return前,会跑到finally块里面去执行代码,而finally代码是执行return,就直接停止方法了,这种结果就会造成finally的结果将try的结果进行一个覆盖
public static int num(){ try { return 5; } catch (Exception e) { e.printStackTrace(); }finally { return 0; } }
finalize: Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的,但是什么时候调用 finalize 没有保证。
1.1.9 String、StringBuffer与StringBuilder的区别?
第一点: 可变和适用范围。String对象是不可变的,而StringBuffer和StringBuilder是可变字符序列。每次对String的操作相当于生成一个新的String对象,而对StringBuffer和StringBuilder的操作是对对象本身的操作,而不会生成新的对象,所以对于频繁改变内容的字符串避免使用String,因为频繁的生成对象将会对系统性能产生影响。
第二点: 线程安全。String由于有final修饰,安全性是简单而纯粹的。StringBuilder和StringBuffer的区别在于StringBuilder不保证同步,也就是说如果需要线程安全需要使用StringBuffer,不需要同步的StringBuilder效率更高
1.1.10 接口与抽象类的区别?
- 一个子类只能继承一个抽象类, 但能实现多个接口
- 抽象类可以有构造方法, 接口没有构造方法
- 抽象类可以有普通成员变量, 接口没有普通成员变量
- 抽象类和接口都可有静态成员变量, 抽象类中静态成员变量访问类型任意,接口只能public static final(默认)
- 抽象类可以没有抽象方法, 抽象类可以有普通方法;接口在JDK8之前都是抽象方法,在JDK8可以有default方法,在JDK9中允许有私有普通方法
- 抽象类可以有静态方法;接口在JDK8之前不能有静态方法,在JDK8中可以有静态方法,且只能被接口类直接调用(不能被实现类的对象调用)
- 抽象类中的方法可以是public、protected; 接口方法在JDK8之前只有public abstract,在JDK8可以有default方法,在JDK9中允许有private方法
1.1.10 this() & super()在构造方法中的区别?
- 调用super()必须写在子类构造方法的第一行, 否则编译不通过
- super从子类调用父类构造, this在同一类中调用其他构造均需要放在第一行
- 尽管可以用this调用一个构造器, 却不能调用2个
- this和super不能出现在同一个构造器中, 否则编译不通过
- this()、super()都指的对象,不可以在static环境中使用
- 本质this指向本对象的指针。super是一个关键字
1.2 泛型
1.2.1 为什么需要泛型
让我们先来看看没有泛型的世界是什么样的:机械且重复
private static int add(int a, int b) {
System.out.println(a + "+" + b + "=" + (a + b));
return a + b;
}
private static float add(float a, float b) {
System.out.println(a + "+" + b + "=" + (a + b));
return a + b;
}
private static double add(double a, double b) {
System.out.println(a + "+" + b + "=" + (a + b));
return a + b;
}
拥有泛型的世界:朴实无华干大事
private static <T extends Number> double add(T a, T b) {
System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue()));
return a.doubleValue() + b.doubleValue();
}
所以为什么需要泛型不言而喻,有了它减少我们对代码的维护工作。
1.2.2 如何理解Java中的泛型是伪泛型?(类型擦除)
泛型中类型擦除 Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了“伪泛型”的策略,即Java在语法上支持泛型,但是在编译阶段会进行所谓的“类型擦除”(Type Erasure),将所有的泛型表示(尖括号中的内容)都替换为具体的类型(其对应的原生态类型),就像完全没有泛型一样。如下:
写代码阶段阶段:List<String> list = new ArrayList<>()
编译阶段: List list = new ArrayList();
1.3 注解
1.3.1注解的作用?
注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解。它主要的作用有以下四方面:
- 生成文档: 通过代码里标识的元数据生成javadoc文档。
- 编译检查:通过代码里标识的元数据让编译器在编译期间进行检查验证。
- 编译时动态处理:编译时通过代码里标识的元数据动态处理,例如动态生成代码。(例如:springboot框架中使用的:@Data )
- 运行时动态处理:运行时通过代码里标识的元数据动态处理,例如使用反射注入实例。(例如:@Resource、@Autowired)
1.4 异常
1.4.1 异常部分内容在另一篇文章中,点击跳转----> 异常: