auto commit
This commit is contained in:
parent
5438ab4b60
commit
7746f5d72f
@ -650,7 +650,7 @@ x.equals(null); // false;
|
|||||||
**2. equals() 与 ==**
|
**2. equals() 与 ==**
|
||||||
|
|
||||||
- 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。
|
- 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。
|
||||||
- 对于引用类型,== 判断两个实例是否引用同一个对象,而 equals() 判断引用的对象是否等价,根据引用对象 equals() 方法的具体实现来进行比较。
|
- 对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Integer x = new Integer(1);
|
Integer x = new Integer(1);
|
||||||
@ -663,7 +663,7 @@ System.out.println(x == y); // false
|
|||||||
|
|
||||||
- 检查是否为同一个对象的引用,如果是直接返回 true;
|
- 检查是否为同一个对象的引用,如果是直接返回 true;
|
||||||
- 检查是否是同一个类型,如果不是,直接返回 false;
|
- 检查是否是同一个类型,如果不是,直接返回 false;
|
||||||
- 将 Object 实例进行转型;
|
- 将 Object 对象进行转型;
|
||||||
- 判断每个关键域是否相等。
|
- 判断每个关键域是否相等。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@ -694,11 +694,11 @@ public class EqualExample {
|
|||||||
|
|
||||||
## hashCode()
|
## hashCode()
|
||||||
|
|
||||||
hasCode() 返回散列值,而 equals() 是用来判断两个实例是否等价。等价的两个实例散列值一定要相同,但是散列值相同的两个实例不一定等价。
|
hasCode() 返回散列值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。
|
||||||
|
|
||||||
在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个实例散列值也相等。
|
在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象散列值也相等。
|
||||||
|
|
||||||
下面的代码中,新建了两个等价的实例,并将它们添加到 HashSet 中。我们希望将这两个实例当成一样的,只在集合中添加一个实例,但是因为 EqualExample 没有实现 hasCode() 方法,因此这两个实例的散列值是不同的,最终导致集合添加了两个等价的实例。
|
下面的代码中,新建了两个等价的对象,并将它们添加到 HashSet 中。我们希望将这两个对象当成一样的,只在集合中添加一个对象,但是因为 EqualExample 没有实现 hasCode() 方法,因此这两个对象的散列值是不同的,最终导致集合添加了两个等价的对象。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
EqualExample e1 = new EqualExample(1, 1, 1);
|
EqualExample e1 = new EqualExample(1, 1, 1);
|
||||||
@ -710,7 +710,7 @@ set.add(e2);
|
|||||||
System.out.println(set.size()); // 2
|
System.out.println(set.size()); // 2
|
||||||
```
|
```
|
||||||
|
|
||||||
理想的散列函数应当具有均匀性,即不相等的实例应当均匀分布到所有可能的散列值上。这就要求了散列函数要把所有域的值都考虑进来,可以将每个域都当成 R 进制的某一位,然后组成一个 R 进制的整数。R 一般取 31,因为它是一个奇素数,如果是偶数的话,当出现乘法溢出,信息就会丢失,因为与 2 相乘相当于向左移一位。
|
理想的散列函数应当具有均匀性,即不相等的对象应当均匀分布到所有可能的散列值上。这就要求了散列函数要把所有域的值都考虑进来,可以将每个域都当成 R 进制的某一位,然后组成一个 R 进制的整数。R 一般取 31,因为它是一个奇素数,如果是偶数的话,当出现乘法溢出,信息就会丢失,因为与 2 相乘相当于向左移一位。
|
||||||
|
|
||||||
一个数与 31 相乘可以转换成移位和减法:`31*x == (x<<5)-x`,编译器会自动进行这个优化。
|
一个数与 31 相乘可以转换成移位和减法:`31*x == (x<<5)-x`,编译器会自动进行这个优化。
|
||||||
|
|
||||||
@ -752,7 +752,7 @@ ToStringExample@4554617c
|
|||||||
|
|
||||||
**1. cloneable**
|
**1. cloneable**
|
||||||
|
|
||||||
clone() 是 Object 的 protect 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。
|
clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class CloneExample {
|
public class CloneExample {
|
||||||
@ -795,6 +795,8 @@ java.lang.CloneNotSupportedException: CloneExample
|
|||||||
|
|
||||||
以上抛出了 CloneNotSupportedException,这是因为 CloneExample 没有实现 Cloneable 接口。
|
以上抛出了 CloneNotSupportedException,这是因为 CloneExample 没有实现 Cloneable 接口。
|
||||||
|
|
||||||
|
应该注意的是,clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class CloneExample implements Cloneable {
|
public class CloneExample implements Cloneable {
|
||||||
private int a;
|
private int a;
|
||||||
@ -807,12 +809,9 @@ public class CloneExample implements Cloneable {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
应该注意的是,clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。
|
**2. 浅拷贝**
|
||||||
|
|
||||||
**2. 深拷贝与浅拷贝**
|
拷贝对象和原始对象的引用类型引用同一个对象。
|
||||||
|
|
||||||
- 浅拷贝:拷贝实例和原始实例的引用类型引用同一个对象;
|
|
||||||
- 深拷贝:拷贝实例和原始实例的引用类型引用不同对象。
|
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class ShallowCloneExample implements Cloneable {
|
public class ShallowCloneExample implements Cloneable {
|
||||||
@ -852,6 +851,10 @@ e1.set(2, 222);
|
|||||||
System.out.println(e2.get(2)); // 222
|
System.out.println(e2.get(2)); // 222
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**3. 深拷贝**
|
||||||
|
|
||||||
|
拷贝对象和原始对象的引用类型引用不同对象。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public class DeepCloneExample implements Cloneable {
|
public class DeepCloneExample implements Cloneable {
|
||||||
private int[] arr;
|
private int[] arr;
|
||||||
@ -895,6 +898,8 @@ e1.set(2, 222);
|
|||||||
System.out.println(e2.get(2)); // 2
|
System.out.println(e2.get(2)); // 2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**4. clone() 的替代方案**
|
||||||
|
|
||||||
使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。
|
使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@ -964,7 +969,7 @@ private 方法隐式地被指定为 final,如果在子类中定义的方法和
|
|||||||
|
|
||||||
**1. 静态变量**
|
**1. 静态变量**
|
||||||
|
|
||||||
- 静态变量:类所有的实例都共享静态变量,可以直接通过类名来访问它;静态变量在内存中只存在一份。
|
- 静态变量:又称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它;静态变量在内存中只存在一份。
|
||||||
- 实例变量:每创建一个实例就会产生一个实例变量,它与该实例同生共死。
|
- 实例变量:每创建一个实例就会产生一个实例变量,它与该实例同生共死。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@ -983,7 +988,7 @@ public class A {
|
|||||||
|
|
||||||
**2. 静态方法**
|
**2. 静态方法**
|
||||||
|
|
||||||
静态方法在类加载的时候就存在了,它不依赖于任何实例,所以静态方法必须有实现,也就是说它不能是抽象方法(abstract)。
|
静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,也就是说它不能是抽象方法(abstract)。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public abstract class A {
|
public abstract class A {
|
||||||
@ -1023,7 +1028,6 @@ public class A {
|
|||||||
A a2 = new A();
|
A a2 = new A();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```html
|
```html
|
||||||
@ -1055,12 +1059,12 @@ public class OuterClass {
|
|||||||
|
|
||||||
**5. 静态导包**
|
**5. 静态导包**
|
||||||
|
|
||||||
|
在使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低。
|
||||||
|
|
||||||
```java
|
```java
|
||||||
import static com.xxx.ClassName.*
|
import static com.xxx.ClassName.*
|
||||||
```
|
```
|
||||||
|
|
||||||
在使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低。
|
|
||||||
|
|
||||||
**6. 初始化顺序**
|
**6. 初始化顺序**
|
||||||
|
|
||||||
静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。
|
静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。
|
||||||
@ -1102,11 +1106,12 @@ public InitialOrderTest() {
|
|||||||
- 子类(实例变量、普通语句块)
|
- 子类(实例变量、普通语句块)
|
||||||
- 子类(构造函数)
|
- 子类(构造函数)
|
||||||
|
|
||||||
|
|
||||||
# 七、反射
|
# 七、反射
|
||||||
|
|
||||||
每个类都有一个 **Class** 对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着 Class 对象。
|
每个类都有一个 **Class** 对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着 Class 对象。
|
||||||
|
|
||||||
类加载相当于 Class 对象的加载。类在第一次使用时才动态加载到 JVM 中,可以使用 Class.forName("com.mysql.jdbc.Driver") 这种方式来控制类的加载,该方法会返回一个 Class 对象。
|
类加载相当于 Class 对象的加载。类在第一次使用时才动态加载到 JVM 中,可以使用 `Class.forName("com.mysql.jdbc.Driver")` 这种方式来控制类的加载,该方法会返回一个 Class 对象。
|
||||||
|
|
||||||
反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。
|
反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user