Java中的仅支持单继承,却神奇的是每个类都基本上间接或直接继承了Object类。Object类相当于祖宗类了。当然,对于曾n孙类来说,对于祖宗类的方法也确实有继承过来的。也就是说,Object类中的方法每个类里面都或多或少有,要么就是直接被继承过来,要么就是覆盖重写让我所用。那也就是说每个类都有继承 ? 对的。
1.下面我将以String字符串类举例,
如下代码: 给出两个字符串,输出两个字符串并且输出比较的boolean值?可能就有人问了,这么简单你写什么?
-
public
class StringTest {
-
-
public static void main(String[]args) {
-
String string1 =
"csdn";
-
String string2 =
"csdn";
-
-
System.out.println(
"stirng1 = "+string1);
//等于string1.toString()
-
System.out.println(
"string2 = "+string2);
//等于string2.toString()
-
System.out.println(string1.equals(string2));
-
-
}
-
}
仿佛对于字符串的比较equals方法进行比较字面量的值非常理所应当呀,这不就是相同的就返回true,否则返回false吗。对的,你想得没有错。
运行结果也是在情理之中:
2.那么下面我又定义一个Student类,里面包含属性有:姓名和年龄。
-
public
class Student {
-
private String name;
-
private
int age;
-
Student(String name,
int age){
-
this.name=name;
-
this.age = age;
-
}
-
Student(){
-
-
}
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public int getAge() {
-
return age;
-
}
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
}
并且我们用类似于上述的使用String类的方式去实现Student类。
-
public
class StudentTest {
-
public static void main(String[]args) {
-
Student student1 =
new Student(
"xiaobai",
18);
-
Student student2 =
new Student(
"xiaobai",
18);
-
-
System.out.println(student1);
//等于student1.toStirng()
-
System.out.println(student2);
//等于student2.toString()
-
-
System.out.println(student1.equals(student2));
-
-
-
}
-
}
难道他的结果跟String类类似吗?没有,它返回了一连串不知道的东西和false。
那么,这到底是为什么呢?为什么String类直接输出字符串对象名可以输出对应的字符串,为什么equals做比较就是true,而Student类也是一样的字面量却是false呢。
上面所使用的方法中并不是说凭空捏造的,先告诉你 equals() , hashCode() 方法可以规定equals()方法的比较方式,而toString()就可以只输出对象名就可以输出指定要输出的变量值,又恰恰刚好,这几个方法都是Object类中的,他们都间接或直接继承了Object类,也刚好继承了这里面的方法。
但是,继承了这里面的方法并不能完全为我所用,你必须要去覆盖重写方法后重新定义方法的内容才能让方法为我所用。这里的话,之所以编译器对于String类那么听话,就是因为String类按照自己的思路去覆盖重写了这几个方法,让其表达出了String类该有的特征。
Student类中的几个方法的覆盖重写:
1.我们对其Student类继承下来的toString方法覆盖重写
-
public
class Student {
-
private String name;
-
private
int age;
-
Student(String name,
int age){
-
this.name=name;
-
this.age = age;
-
}
-
Student(){
-
-
}
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public int getAge() {
-
return age;
-
}
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
@Override
-
public String toString() {
//对toString覆盖重写
-
return
"Student [name=" + name +
", age=" + age +
"]";
-
}
-
-
-
-
}
然后再编译StudentTest类。这个时候就可以按照输出对象名来输出实例内容啦。
2.对其Student类继承下来的equals方法的覆盖重写。对其equals方法覆盖重写的同时,我们也要对其hashCode方法覆盖重写,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。对于这两个方法可以通过软件进行自动覆盖重写。下面是自动覆盖重写的代码。
-
-
public
class Student {
-
private String name;
-
private
int age;
-
Student(String name,
int age){
-
this.name=name;
-
this.age = age;
-
}
-
Student(){
-
-
}
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public int getAge() {
-
return age;
-
}
-
public void setAge(int age) {
-
this.age = age;
-
}
-
-
@Override
-
public String toString() {
-
return
"Student [name=" + name +
", age=" + age +
"]";
-
}
-
@Override
-
public int hashCode() {
-
final
int prime =
31;
-
int result =
1;
-
result = prime * result + age;
-
result = prime * result + ((name ==
null) ?
0 : name.hashCode());
-
return result;
-
}
-
@Override
-
public boolean equals(Object obj) {
-
if (
this == obj)
-
return
true;
-
if (obj ==
null)
-
return
false;
-
if (getClass() != obj.getClass())
-
return
false;
-
Student other = (Student) obj;
-
if (age != other.age)
-
return
false;
-
if (name ==
null) {
-
if (other.name !=
null)
-
return
false;
-
}
else
if (!name.equals(other.name))
-
return
false;
-
return
true;
-
}
-
-
-
-
}
这样的话,上述的测试的代码就跟String类一模一样啦。如果你觉得这样太复杂,你也可以设置自己的相等方式,前提是要让别人理解你的逻辑哦,并且也要使两个对象equals为true的同时,hashCode的值也要相等。
总结: 某个类覆盖重写继承下来的toString方法,输出类对象名就不会输出地址而是输出你在toString方法里的内容。equals方法和hashCode()方法需要一起覆盖重写。重写之后就可以进行比较对象了。另外Object类还有很多方法,如果需要就可以覆盖重写为我所用
另外,对于这篇文章里涉及的内容我也写了一个应用。如见 Java实现任意对象为结点的单链表很难吗?
转载:https://blog.csdn.net/wasane/article/details/117200801