Loading

Class Object

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;
        }
    }
}
posted @ 2021-06-16 23:35  landfill  阅读(66)  评论(0编辑  收藏  举报