在采用 Object 参数的 Java 方法中,如何访问仅存在于特定类实例的字段?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9901195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 22:49:13  来源:igfitidea点击:

In a Java method that takes an Object argument, how can you access fields that only exist for instances of specific classes?

javaobjectfield

提问by John P

-- Yes, this is a question asking for help regarding something that was assigned as homework. No, this is not me asking you to do my homework for me. The deadline was a half an hour ago; I literally can't change my submission. You'll just have to take my word for it. Moving on...

-- 是的,这是一个关于被分配为家庭作业的问题寻求帮助的问题。不,这不是我要你为我做作业。截止日期是半小时前;我真的无法改变我的提交。你只需要相信我的话。继续...

I know that testing for the type of objects is supposed to be unnecessary. When I was looking for details about 'instanceof', I found a half dozen threads where people responded only to tell the original poster that they were making a mistake if they had to test to find out what kind of object they were dealing with before processing it. Yes, I know, I would love to follow the conventions. Unfortunately, my professor asked for us to override the equals method of a class we defined, and specifically required an Object type parameter. If you see my code, you'll probably understand better:

我知道应该没有必要对对象类型进行测试。当我在寻找有关“instanceof”的详细信息时,我发现了六个主题,人们在这些主题中的回复只是告诉原始发布者,如果他们必须在处理之前进行测试以找出他们正在处理的对象类型,那么他们就犯了错误它。是的,我知道,我很想遵守约定。不幸的是,我的教授要求我们重写我们定义的类的 equals 方法,并且特别需要一个 Object 类型参数。如果你看到我的代码,你可能会更好地理解:

public boolean equals(Course other){
    if(!(other instanceof Course)){
        return false;
    } else if(other.name==this.name && other.days==this.days && 
        other.start==this.start && other.end==this.end){
        return true;
    }
    return false;
}

You can probably understand where I'm going with this. The 'other' parameter should be an Object type, but the program has a fit if I leave it as an Object and use the name / days / start / end fields. If I change it to Course, of course it works (no pun intended), but that would be a completely different method. The desired behavior is for all objects other than Course instances to make the method return false, and additionally, for mismatched data between Course instances to make it return false.

你可能会理解我的意思。'other' 参数应该是一个对象类型,但如果我将它保留为一个对象并使用名称/天/开始/结束字段,则程序适合。如果我将其更改为 Course,当然可以工作(没有双关语),但这将是一种完全不同的方法。所需的行为是让除 Course 实例之外的所有对象使该方法返回 false,此外,对于 Course 实例之间不匹配的数据使其返回 false。

I'm sorry to all of you who know Java well enough to be frustrated by seeing questions like these.

我很抱歉所有对 Java 足够了解但看到这些问题而感到沮丧的人。

回答by jabu.10245

If you want to override the "equals" method, you should use Object as a parameter, and thus you have to checkfor the object's type. Usually your own implementation would look like this:

如果要覆盖“equals”方法,则应使用 Object 作为参数,因此必须检查对象的类型。通常你自己的实现看起来像这样:

@Override
public boolean equals(Object obj) {
    if (obj == this)
        return true;  // object's references are identical
    else if (!(obj instanceof Course))
        return false;

    Course that = (Course) obj;
    return (this.name.equals(that.name)) && (this.days == that.days)
        && (this.start.equals(that.start)) && (this.end.equals(that.end));
}

Of course you should override "hashCode" as well, using the same significant fields.

当然,您也应该使用相同的重要字段覆盖“hashCode”。



Instead, you overloadedthe method with your own parameter of type Course. So if you call myobject.equals(anotherObject)and anotherObjectis notof type Course, your "equals" method will never be called, instead the Object#equalsmethod will be called, which does only the following: return this == obj.

相反,您使用自己的 Course 类型参数重载了该方法。所以,如果你myobject.equals(anotherObject)anotherObject没有类型的课程,你的“等于”方法永远不会被调用,而不是Object#equals方法将被调用,仅执行以下操作:return this == obj



The reason why overloading the "equals" method is not enough is the necessity to overload "hashCode" as well, which takes no parameters and thus cannot be overloaded.

之所以重载“equals”方法还不够,是因为还需要重载“hashCode”,它不带参数,因此无法重载。

  • If you write your own implementation of boolean equals(Object), you mustalso implement int hashCode()
  • Both methods should use the same significant fields for "hashCode" and "equals".
  • If a.equals(b) == truethan the following mustbe also true: a.hashCode() == b.hashCode()
  • Also if a.hashCode() != b.hashCode()then a.equals(b) == false
  • 如果您编写自己的 实现boolean equals(Object),则还必须实现int hashCode()
  • 两种方法都应该对“hashCode”和“equals”使用相同的重要字段。
  • 如果a.equals(b) == true不是下面必须是也是如此:a.hashCode() == b.hashCode()
  • 此外,如果a.hashCode() != b.hashCode()a.equals(b) == false

The last point is the main reason why you should not just overload "equals" with your own type:

最后一点是你不应该只用你自己的类型重载“equals”的主要原因:

Course c1 = new Course("myname");
Course c2 = new Course("myname");
c1.equals(c2);                   // true
c1.hashCode() == c2.hashCode();  // false

回答by LazyCubicleMonkey

You can cast Object as Course:

您可以将对象转换为课程:

Course course = (Course)object;

Then do all the comparisons on the course object. Obviously, still do the instanceof check before casting to avoid a ClassCastException.

然后对课程对象进行所有比较。显然,在强制转换之前仍然进行 instanceof 检查以避免 ClassCastException。

回答by SLaks

You're trying to castit:

你试图投射它:

Cource c = (Course)other;

回答by Alex Calugarescu

Your code :

你的代码:

 public boolean equals(Course other){
     if(!(other instanceof Course)){  <-- other can only be Course here
          return false;
     } else if(other.name==this.name && other.days==this.days && 
         other.start==this.start && other.end==this.end){
         return true;
      }
     return false;
  }

Correct code :

正确的代码:

  public boolean equals(Object other){
     if(!(other instanceof Course)){
         return false;
     } else{ 
       Course c = (Course) other;
       if(c.name==this.name && c.days==this.days && 
          c.start==this.start && c.end==this.end){
         return true;
      }
     }
   } 
     return false;
  }