Java中 == 和 equals 和 hashCode 的区别
对于关系操作符 ==
-
若操作数的类型是基本数据类型,则该关系操作符判断的是左右两边操作数的值是否相等
-
若操作数的类型是引用数据类型,则该关系操作符判断的是左右两边操作数的内存地址是否相同。也就是说,若此时返回true,则该操作符作用的一定是同一个对象。
对于使用 equals 方法,内部实现分为三个步骤:
-
先比较引用是否相同(是否为同一对象),
-
再判断类型是否一致(是否为同一类型),
-
最后比较内容是否一致
Java 中所有内置的类的 equals 方法的实现步骤均是如此,特别是诸如 Integer,Double 等包装器类。如以下 String
中的 equals
方法实现
// String.java
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
复制代码
hashcode是系统用来快速检索对象而使用
equals方法本意是用来判断引用的对象是否一致
重写equals方法和hashcode方法时,equals方法中用到的成员变量也必定会在hashcode方法中用到,只不过前者作为比较项,后者作为生成摘要的信息项,本质上所用到的数据是一样的,从而保证二者的一致性
int、char、long各占多少字节数
Java 基本类型占用的字节数
-
1字节: byte , boolean
-
2字节: short , char
-
4字节: int , float
-
8字节: long , double
注:1字节(byte)=8位(bits)
int与integer的区别
-
Integer是int的包装类,int则是java的一种基本数据类型
-
Integer变量必须实例化后才能使用,而int变量不需要
-
Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
-
Integer的默认值是null,int的默认值是0
对 Java 多态的理解
多态是指父类的某个方法被子类重写时,可以产生自己的功能行为,同一个操作作用于不同对象,可以有不同的解释,产生不同的执行结果。
多态的三个必要条件:
-
继承父类。
-
重写父类的方法。
-
父类的引用指向子类对象
然后可以使用结合里氏替换法则进一步的谈理解
里氏替换法则 ---- 所有引用基类的地方必须能透明地使用其子类的对象
- 子类必须完全实现父类的方法
注意 在类中调用其他类时务必要使用父类或接口,如果不能使用父类或接口,则说明类的设计已经违背了LSP原则
注意 如果子类不能完整地实现父类的方法,或者父类的某些方法在子类中已经发生“畸变”,则建议断开父子继承关系,采用依赖、聚集、组合等关系代替继承
-
子类可以有自己的个性
-
覆盖或实现父类的方法时输入参数可以被放大
-
覆写或实现父类的方法时输出结果可以被缩小
在项目中,采用里氏替换原则时,尽量避免子类的“个性”,一旦子类有“个性”,这个子类和父类之间的关系就很难调和了, 把子类当做父类使用,子类的“个性”被抹杀——委屈了点;把子类单独作为一个业务来使用,则会让代码间的耦合关系变得扑朔迷离——缺乏类替换的标准
String、StringBuffer、StringBuilder 区别
StringBuffer 和 String 一样都是用来存储字符串的,只不过由于他们内部的实现方式不同,导致他们所使用的范围不同,对于 StringBuffer 而言,他在处理字符串时,若是对其进行修改操作,它并不会产生一个新的字符串对象,所以说在内存使用方面它是优于 String 的
StringBuilder 也是一个可变的字符串对象,他与 StringBuffer 不同之处就在于它是线程不安全的,基于这点,它的速度一般都比 StringBuffer 快
String 字符串的拼接会被 JVM 解析成 StringBuilder 对象拼接,在这种情况下 String 的速度比 StringBuffer 的速度快
str +=”b”等同于 str = new StringBuilder(str).append(“b”).toString();
详解内部类
内部类使得多重继承的解决方案变得更加完整
使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响
使用内部类才能实现多重继承
-
内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立。
-
在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。
-
创建内部类对象的时刻并不依赖于外围类对象的创建。
-
内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。
-
内部类提供了更好的封装,除了该外围类,其他类都不能访问。
当我们在创建某个外围类的内部类对象时,此时内部类对象必定会捕获一个指向那个外围类对象的引用,只要我们在访问外围类的成员时,就会用这个引用来选择外围类的成员
成员内部类
在成员内部类中要注意两点,
-
成员内部类中不能存在任何 static 的变量和方法
-
成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类
静态内部类
静态内部类与非静态内部类之间存在一个最大的区别,我们知道非静态内部类在编译完成之后会隐含地保存着一个引用,该引用是指向创建它的外围内,但是静态内部类却没有。没有这个引用就意味着:
-
它的创建是不需要依赖于外围类的。
-
它不能使用任何外围类的非static成员变量和方法。
为什么Java里的匿名内部类只能访问final修饰的外部变量?
匿名内部类用法
public class TryUsingAnonymousClass {
public void useMyInterface() {
final Integer number = 123;
System.out.println(number);
MyInterface myInterface = new MyInterface() {
@Override
public void doSomething() {
System.out.println(number);
}
};
myInterface.doSomething();
System.out.println(number);
}
}
复制代码
编译后的结果
class TryUsingAnonymousClass$1
implements MyInterface {
private final TryUsingAnonymousClass this$0;
private final Integer paramInteger;
TryUsingAnonymousClass$1(TryUsingAnonymousClass this$0, Integer paramInteger) {
this.this$0 = this$0;
this.paramInteger = paramInteger;
}
public void doSomething() {
System.out.println(this.paramInteger);
}
}
复制代码
因为匿名内部类最终用会编译成一个单独的类,而被该类使用的变量会以构造函数参数的形式传递给该类,例如:Integer paramInteger,如果变量 不定义成final的,paramInteger在匿名内部类被可以被修改,进而造成和外部的paramInteger不一致的问题,为了避免这种不一致的情况,因为Java 规定匿名内部类只能访问final修饰的外部变量
抽象类和接口的区别
-
默认的方法实现抽象类可以有默认的方法实现完全是抽象的。接口根本不存在方法的实现
-
实现抽象类使用 extends 关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。子类使用关键字 implements 来实现接口。它需要提供接口中所有声明的方法的实现。
-
抽象类可以有构造器,而接口不能有构造器
-
抽象方法可以有public、protected和default这些修饰符。接口方法默认修饰符是public。你不可以使用其它修饰符。
-
抽象类在java语言中所表示的是一种继承关系,一个子类只能存在一个父类,但是可以存在多个接口。
-
抽象方法比接口速度要快,接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
图片转存中…(img-VCYMa9Vk-1715704662350)]
[外链图片转存中…(img-sFEzCOVo-1715704662351)]
[外链图片转存中…(img-4YZpUTUf-1715704662351)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,不论你是刚入门Java开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!