【问题标题】:Making class with makes subclass object unique with hashCode and equals使用 hashCode 和 equals 创建类使子类对象唯一
【发布时间】:2015-04-18 08:53:37
【问题描述】:

我有LatLotoTicket.java:

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

public class LatLotoTicket {
    private static int counterID = 0;
    private final int id = counterID++;
    private final String address;
    private final Set<Integer> userNumbers;

    public LatLotoTicket(String address, Set<Integer> userNumbers) {
        this.address = address;
        this.userNumbers = userNumbers;
    }

    public LatLotoTicket(LatLotoTicket ticket) {
        this.address = ticket.address;
        this.userNumbers = ticket.getUserNumbers();
    }

    public String getAddress() {
        return address;
    }

    public Set<Integer> getUserNumbers() {
        return new HashSet<>(userNumbers);
    }

    @Override
    public boolean equals(Object o) {
        if(this == o) return true;
        if(o == null || getClass() != o.getClass()) return false;
        LatLotoTicket that = (LatLotoTicket) o;
        return Objects.deepEquals(this.id, that.id);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id);
    }


}

我想我可以制作一个扩展这个LatLotoTicket 类的模板类。并在那里使 id 唯一并提供自己的 hashCodeequals 方法,但我不知道如何使每个模板都有自己的静态 idCounterid 实例。

我尝试制作具有以下内容的模板类​​:

  1. classIDCounter - with 将为扩展此对象的每个新类分配 id
  2. classID - 这将避免将两个不同的对象与相同的 id 进行比较。
  3. IDCounter - 分别计算每个类的单个对象 id
  4. id - 包含每个对象的 id

Foo 和 Bar 类:

public class Foo extends Unique<Foo> {
   public Foo() {
       System.out.println("Object ID "super.id + " class id " + super.classID)
   }
}

public class Bar extends Unique<Bar> {
   public Foo() {
       System.out.println("Object ID "super.id + " class id " + super.classID)
   }
}

在 main.java 中:

Foo foo1 = new Foo(); // Object ID 1 class id 1
Foo foo2 = new Foo(); // Object ID 2 class id 1
Bar bar1 = new Bar(); // Object ID 1 class id 2
Bar bar2 = new Bar(); // Object ID 2 class id 2
Foo foo3 = new Foo(); // Object ID 3 class id 1

我走了这么远(基本上什么都没有),现在我不知道该怎么办。 Unique.java:

import java.util.Objects;

public class Unique<Child> {
    private static int classIDCounter = 0;
    private final int classID = classIDCounter++;

    private static int IDCounter = 0;
    private final int id = IDCounter++;

    @Override
    public boolean equals(Object o) {
        if(this == o) return true;
        if(o == null || getClass() != o.getClass()) return false;
        Unique unique = (Unique) o;
        return Objects.deepEquals(classID, unique.classID);
    }

    @Override
    public int hashCode() {
        int result = classID;
        result = 31 * result + id;
        return result;
    }
}

我怎样才能做到这一点?还有没有内置的类可以做到这一点?

我正在使用 JAVA 8。

【问题讨论】:

    标签: java templates hash


    【解决方案1】:

    在这里。

    public class Unique {
    
        private static final Map<Class, AtomicInteger> idCounters = new HashMap<>();
        private static final Map<Class, Integer> classIDs = new HashMap<>();
        private static int classIDCounters2 = 0;
    
        private final int id;
    
        public Unique() {
            this.id = nextIdFor(getClass());
        }
    
        private static int nextIdFor(Class<? extends Unique> aClass) {
            AtomicInteger counter = idCounters.get(aClass);
            if(counter == null){
                counter = new AtomicInteger(0);
                idCounters.put(aClass, counter);
            }
            return counter.incrementAndGet();
        }
    
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Unique unique = (Unique) o;
            return getClassID() == unique.getClassID() && getId() == unique.getId();
        }
    
        @Override
        public int hashCode() {
            int result = getClassID();
            result = 31 * result + getId();
            return result;
        }
    
        public int getId() {
            return id;
        }
    
        public int getClassID() {
            Integer classId = classIDs.get(getClass());
            if(classId == null){
                classId = classIDCounters2++;
                classIDs.put(getClass(), classId);
            }
            return classId;
        }
    }
    

    但请记住,它不是线程安全的。而且它很慢。而且你最好不要使用它,因为它很难闻。

    【讨论】:

    • getClassID() 毫无用处,因为你总是有getClass()
    • 这只是为了说明。不能只为特定模板类型创建静态实例并访问它吗?我知道它可以在java中完成。如果我有很多 id 的课程,那么我应该怎么做?
    • 没有。你不能。事实上Foo&lt;Bar&gt;Foo&lt;Baz&gt; 有相同的Class 实例与之关联。关于第二个问题。您应该将 id 的生成与类的创建分开。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 2013-11-02
    • 2021-11-17
    • 1970-01-01
    • 2011-08-08
    • 2022-11-04
    相关资源
    最近更新 更多