1.
Object
类
Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。
Object 类可以显示继承,也可以隐式继承,以下两种方式时一样的:
public class Runoob extends Object{ }
public class Runoob { }
序号 | 方法 |
---|---|
1 | protected Object clone()创建并返回一个对象的拷贝 |
2 | boolean equals(Object obj)比较两个对象是否相等 |
3 | protected void finalize()当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此方法。 protected void finalize() throws Throwable { } 空方法 |
4 | Class getClass()获取对象的运行时对象的类 |
5 | int hashCode()获取对象的 hash 值 |
6 | void notify()唤醒在该对象上等待的某个线程 |
7 | void notifyAll()唤醒在该对象上等待的所有线程 |
8 | String toString()返回对象的字符串表示形式 |
9 | void wait()让当前线程进入等待状态。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。 |
10 | void wait(long timeout)让当前线程处于等待(阻塞)状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过参数设置的timeout超时时间。 |
11 | void wait(long timeout, int nanos)与 wait(long timeout) 方法类似,多了一个 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒。 |
wait,notify,hashCode,notifyAll,clone,getClass都是本地方法
2. equals()
equals() 定义在JDK的Object.java中。通过判断两个对象的地址是否相等(即,是否是同一个对象)来区分它们是否相等。源码如下:
public boolean equals(Object obj) { return (this == obj); '//比较内存地址 }
没有重写比较的是内存地址,是不是指向同一个内存对象。
重写一般是比较内容是否相同。
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(name, person.name) && Objects.equals(age, person.age); } // Object.equals(a,b) 比较地址,是否为同一个对象 public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); }
== :对象比较地址,基本类型比较值
equals: 没有重写就是==,重写了比较内容
3. hashCode()
重写hashCode()
@Override public int hashCode() { return Objects.hash(name, age); }
// package java.util.Objects public static int hashCode(Object o) { return o != null ? o.hashCode() : 0; } public static int hash(Object... values) { return Arrays.hashCode(values); } // package java.util.Arrays public static int hashCode(Object a[]) { if (a == null) return 0; int result = 1; for (Object element : a) result = 31 * result + (element == null ? 0 : element.hashCode()); return result; } // java.lang.String重写了HashCode public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; } // package java.lang.Object 本地方法实现 public native int hashCode();
public static void main(String[] args) { Person tom = new Person("TOM", "12"); System.out.println(tom.hashCode()); System.out.println("TOM".hashCode()); System.out.println(new Integer(12).hashCode()); } /* 2583280 83250 12 */
HashCode的作用
虽然,每个Java类都包含hashCode() 函数。但是,仅仅当创建并某个“类的散列表”(如HashMap,Hashtable,HashSet)时,该类的hashCode() 才有用(作用是:确定该类的每一个对象在散列表中的位置;其它情况下(例如,创建类的单个对象,或者创建类的对象数组等等),类的hashCode() 没有作用。
也就是说:hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
在使用HashMap等结构的时候,可能会出现Hash Collision,此时才需要equals(),平时这两个方法没有什么关系。
HashCode不同的对象一定不相等
相同的对象HashCode一定相等
HashCode相等,也可能是不同的对象
4. toString()
// java.lang.Object() public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); // java.lang.Object - 类名 // @ - 符号 // d716361 - 哈希值的十六进制值 }
class RunoobTest { public static void main(String[] args) { // toString() with Object Object obj1 = new Object(); System.out.println(obj1.toString()); Object obj2 = new Object(); System.out.println(obj2.toString()); Object obj3 = new Object(); System.out.println(obj3.toString()); } } /* java.lang.Object@d716361 java.lang.Object@6ff3c5b5 java.lang.Object@3764951d */
// 重写toString() @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}'; } // Person{name='TOM', age='12'}
5. Lombok
常用的几个注解:
@Data : 注在类上,提供类的get、set、equals、hashCode、canEqual、toString方法
@AllArgsConstructor : 注在类上,提供类的全参构造
@NoArgsConstructor : 注在类上,提供类的无参构造 [Java的构造函数与默认构造函数]
@Setter : 注在属性上,提供 set 方法
@Getter : 注在属性上,提供 get 方法
@EqualsAndHashCode : 注在类上,提供对应的 equals 和 hashCode 方法
@Log4j/@Slf4j : 注在类上,提供对应的 Logger 对象,变量名为 log
@Data is a convenient shortcut annotation that bundles the features of @ToString, @EqualsAndHashCode, @Getter / @Setter and @RequiredArgsConstructor together: In other words, @Data generates all the boilerplate that is normally associated with simple POJOs (Plain Old Java Objects) and beans: getters for all fields, setters for all non-final fields, and appropriate toString, equals and hashCode implementations that involve the fields of the class, and a constructor that initializes all final fields, as well as all non-final fields with no initializer that have been marked with @NonNull, in order to ensure the field is never null.
@RequiredArgsConstructor
@RequiredArgsConstructor也是在类上使用,但是这个注解可以生成带参或者不带参的构造方法。
若带参数,只能是类中所有带有 @NonNull注解的和以final修饰的未经初始化的字段
@RequiredArgsConstructor public class User { private final String gender; @NonNull private String username; private String password; } // 编译后: public class User { private final String gender; @NonNull private String username; private String password; public User(String gender, @NonNull String username) { if (username == null) { throw new NullPointerException("username is marked @NonNull but is null"); } else { this.gender = gender; this.username = username; } } }