【问题标题】:Avoid same value in parameter argument in object避免在对象的参数参数中使用相同的值
【发布时间】:2020-01-23 06:50:43
【问题描述】:

假设我像这样在 Java 中创建一个对象

Student std1 = new Student("Tom", "male");

我需要防止另一个对象(例如:std2、std3 等)具有与 std1 相同的值。怎么做?

[编辑] 我想要的例子是:

不允许: Student std2 = new Student("Tom", "male");

允许:Student std2 = new Student("Not Tom", "male");Student std2 = new Student("Tom", "female");Student std2 = new Student("John", "male");

谢谢

【问题讨论】:

  • 不,您不需要 / 应该这样做。您可能想要的是禁止将具有相同数据的第二个 Student 实例持久化或添加到 Course 或其他任何东西,但是您应该禁止创建对象本身。
  • 是否允许 new Student("Tom", "female")new Student("Not Tom", "male")?不清楚您所说的“相同值”是什么意思...
  • 我认为您需要一个嵌入式 ID。如果您尝试创建具有重复值的对象,则不允许这样做。
  • 您可以通过添加连接名称、性别来创建静态字符串哈希集。所以你的 HashSet 中的数据看起来像Tom,maleTom,femaleJohn,male。在Student类的参数化构造函数中,如果其中没有Name,Gender,您可以检查HashSet,然后实例化和对象。类似的东西!

标签: java oop object parameters arguments


【解决方案1】:

您可以通过添加连接名称、性别来创建静态字符串哈希集。

class YourClass {
   public static Set<String> studentSet = new HashSet<>();

   public static void addStudent(String name, String gender) {
     YourClass.studentSet.add(name + "," + gender);
   }

   public static Boolean studentExists(String name, String gender) {
     return YourClass.studentSet.constains(name + "," + gender);
}

所以 HashSet 中的数据看起来像 Tom,male , Tom,female, John,male。

class Student {
...

public Student(String name, String gender) {
    this.name = name;
    this.gender = gender;
    YourClass.addStudent(name, gender);
  }
}

在创建 Student 的实例时,您可以检查 HashSet 是否其中没有 Name、Gender,然后实例化和对象。

if(!YourClass.studentExists(name, gender)) {
    Student student = new Student(name, gender);
}

希望能解决你的问题

【讨论】:

    【解决方案2】:

    假设“值”指的是学生的姓名,我建议您编写一个小函数,如果姓名已被使用,则该函数将返回 true。为此,您可以将所有“学生”存储在 ArrayList 中:

    ArrayList<Student> students = new ArrayList<Student>();
    

    现在您可以将学生添加到此 ArrayList,如下所示:

    private boolean nameIsAlreadyTaken(ArrayList<Student> students, String newName){
        for (int i = 0; i < student.size(); i++){
            if(students.get(i).getName().equals(newName)){
                return true;
            }
        }
        return false;
    }
    

    (您需要在学生类中定义一个 getName() 函数才能使其工作。)

    那么你可以这样做:

    String newName = "迈克尔"; 字符串 newGender = "男";

    if (!nameIsAlreadyTaken(students, newName)){
    students.add(new Student(newName, newGender));
    } else{
        //something you want to to if the name is already taken
    }
    

    您可以在不将 student-ArrayList 传递给函数的情况下执行此操作,但这取决于您。

    【讨论】:

      【解决方案3】:

      我会说你需要重写StudentequalshashCode 方法,然后如果存在这样的学生,则检查构造函数。关于这一点的好答案:link

      import java.util.*;
      
      public class Student {
          private static final Set<Student> REGISTERED_STUDENTS = new HashSet<>();
      
          private String name;
          private String gender;
      
          public static Collection<Student> getRegisteredStudents() {
              return Collections.unmodifiableCollection(REGISTERED_STUDENTS);
          }
      
          public Student(final String name, final String gender) {
              this.name = name;
              this.gender = gender;
      
              if (REGISTERED_STUDENTS.contains(this))
                  throw DuplicateStudentException();
      
              REGISTERED_STUDENTS.add(this);
          }
      
          @Override
          public int hashCode() {
              return Objects.hash(name, gender);
          }
      
          @Override
          public boolean equals(final Object o) {
              if (this == o) return true;
              if (!(o instanceof Student)) return false;
              final Student student = (Student) o;
              return Objects.equals(name, student.name) && Objects.equals(gender, student.gender);
          }
      }
      

      请注意,此示例不是线程安全的,并且使用了在构造函数中直接抛出异常的有争议的解决方案。可能你会想要一个工厂方法和ConcurrentSkipListSet 或另一个线程安全的集合,像这样:

      class Student {
          private static final Set<Student> REGISTERED_STUDENTS = new ConcurrentSkipListSet<>(Comparator.comparing(Student::getName).thenComparing(Student::getGender));
      
          private String name;
          private String gender;
      
          public static Set<Student> getRegisteredStudents() {
              return Collections.unmodifiableSet(REGISTERED_STUDENTS);
          }
      
          public static void addStudent(final String name, final String gender) {
              Student probablyExists = new Student(name, gender);
              REGISTERED_STUDENTS.add(probablyExists);
          }
      
          private Student(final String name, final String gender) {
              this.name = name;
              this.gender = gender;
          }
      
          public String getName() {
              return name;
          }
      
          public String getGender() {
              return gender;
          }
      
          @Override
          public int hashCode() {
              return Objects.hash(name, gender);
          }
      
          @Override
          public boolean equals(final Object o) {
              if (this == o) return true;
              if (!(o instanceof Student)) return false;
              final Student student = (Student) o;
              return Objects.equals(name, student.name) && Objects.equals(gender, student.gender);
          }
      }
      

      【讨论】:

        【解决方案4】:

        您可以创建一个类来控制对象的创建 - 基本上使用享元模式。

        步骤 1. 将 Student 包的构造函数设为私有

        public class Student {
            Student(String name, String gender) {
            ...
        

        步骤 2. 在 Student 中实现 equals 方法

           public boolean equals (Object other) {
               if (!(other instanceof Student)) return false;
               Student otherStudent = (Student) other;
               return Objects.equals(otherStudent.getName(), this.getName()) && Objects.equals(otherStudent.getGender(), this.getGender());
           }
        

        第 3 步。在同一个包中实现一个 Student 对象池

        public class StudentPool {
            private List<Student> students = new ArrayList<>();
        
            public Student getOrCreate(String name, String gender) {
                Student student = new Student(name, gender);
                return students.stream()
                        .filter(s -> Objects.equals(s, student))
                        .findFirst()
                        .orElseGet(() -> {
                            students.add(student);
                            return student;
                        });
            }
        
            public List<Student> get(String name) {
                return students.stream()
                        .filter(student -> Objects.equals(student.getName(), name))
                        .collect(Collectors.toList());
            }
        }
        

        【讨论】:

        • 由于 OP 希望名称 + 性别组合是唯一的(不仅仅是名称),因此您需要创建一个结合这两个值的键,而不是使用名称作为键
        猜你喜欢
        • 2019-11-15
        • 2023-02-01
        • 2014-11-13
        • 1970-01-01
        • 1970-01-01
        • 2011-06-12
        • 1970-01-01
        • 2019-02-22
        • 1970-01-01
        相关资源
        最近更新 更多