文章目录
- 处理Java对象
- 打印对象和toString()方法
- 代码示例
- ==和equals()方法
- 代码示例
- `"hello"`直接量和`new String("hello")`有什么区别?
- 常量池
- `JVM使用常量池管理字符串直接量`代码示例
- `equals()`方法
- 通常正确地重写`equals()方法`应该满足下列条件
- 总结
处理Java对象
Java对象都是Object类的实例,都可直接调用该类中定义的方法,这些方法提供了处理Java对象的通用方法。
打印对象和toString()方法
toString()方法是Object类里的一个实例方法,所有的Java类都是Object类的子类,因此所有的Java对象都具有toString()方法。
package com.abc.part5;
public class PersonTest {
public static void main(String[] args) {
Person p = new Person("小花花");
//com.abc.part5.Person@60e53b93
System.out.println(p);
/**
* 所有的 Java 对象都可以和字符串进行连接运算,当 Java 对象和字符串进行连接运算时,
* 系统自动调用 Java 对象 toString()方法的返回值和字符串进行连接运算。
*/
//com.abc.part5.Person@60e53b93
System.out.println(p + "");
//com.abc.part5.Person@60e53b93
System.out.println(p.toString() + "");
}
}
- toString()方法功能:当程序员直接打印该对象时,系统将会输出该对象的"自我描述"信息,用以告诉外界该对象具有的状态信息。
-
Object类
提供的toString()
方法总是返回该对象实现类
的类名+@+hashCode
值,这个返回值并不能真正实现自我描述
的功能,因此如果用户需要自定义类
能实现自我描述
的功能,就必须重写Object类
的toString()
方法。
代码示例
package com.abc.part5;
public class Apple {
private String color;
private double price;
public Apple(String color, double price) {
this.color = color;
this.price = price;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
/**
* @return String
*/
@Override
public String toString() {
return "水果市场里的" + color + "的苹果的价格是每斤" + price + "元。";
}
}
package com.abc.part5;
public class AppleTest {
public static void main(String[] args) {
Apple apple = new Apple("红色", 3.99);
//水果市场里的红色的苹果的价格是每斤3.99元。
System.out.println(apple.toString());
}
}
从上面运行结果可以看出,通过重写Apple类的toString()
方法,就可以让系统在打印Apple对象时打印出该对象的"自我描述"信息。
- 大部分时候,重写
toString()
方法总是返回该对象的所有令人感兴趣的信息所组成的字符串。通常可返回如下格式的宇符串:
类名[field1=value1, field2=value2]
==和equals()方法
Java程序中测试两个变量是否相等的两种方式
==
运算符
- 当使用
==
来判断两个变量是否相等时
- 两个变量是
基本类型变量
时,只要两个变量的值相等,就将返回true。 - 两个变量是
引用类型变量
时,只有它们指向同一个对象
时,==
判断才会返回true
。==
不可用于比较类型上没有父子关系
的两个对象
。
equals()
方法
- 判断两个
引用类型变量
是否相等
代码示例
package com.abc.part5;
/**
* @Auther: ABC
* @Date: 2020/5/24 15:36
* @Description:
*/
public class EqualTest {
public static void main(String[] args) {
int aa = 65;
float ab = 65.0f;
//aa是否与ab相等?true
System.out.println("aa是否与ab相等?" + (aa == ab));
char ac = 'A';
//aa是否与ac相等?true
System.out.println("aa是否与ac相等?" + (aa == ac));
String s1 = new String("hello");
String s2 = new String("hello");
//s1是否与s2相等?false
System.out.println("s1是否与s2相等?" + (s1 == s2));
//s1是否equals s2?true
System.out.println("s1是否equals s2?" + (s1.equals(s2)));
//由于java.laηg.String与EqualTest类没有继承关系,所以下面语句导致编译错误
//System.out.println("hello" = new EqualTest());
}
}
"hello"
直接量和new String("hello")
有什么区别?
- 当Java程序直接使用形如
"hello"
的字符串直接量(包括可以在编译时就计算出来的字符串值)时,JVM将会使用**常量池
**来管理这些字符串; - 当使用
new String("hello")
时,JVM会先使用常量池
来管理"hello"
直接量,再调用String类
的构造器
来创建一个新的String对象
,新创建的String对象
被保存在堆内存中。
总结一下,new String("hello")
共产生了两个字符串对象。
常量池
常量池(constant pool)
专门用于管理在编译时
被确定并被保存在已编译的.class
文件中的一些数据。它包括了关于类
、方法
、接口中的常量
,还包括字符串常量
。
JVM使用常量池管理字符串直接量
代码示例
package com.abc.part5;
/**
* @Auther: ABC
* @Date: 2020/5/24 15:55
* @Description:
*/
public class StringComapareTest {
public static void main(String[] args) {
//s1直接引用常量池中的"疯狂Java"
String s1 = "疯狂Java";
String s2 = "疯狂";
String s3 = "Java";
//s4后面的字符串值可以在编译时就确定下来
//s4直接引用常量池中的"疯狂Java"
String s4 = "疯狂" + "Java";
//s5后面的字符息值可以在编译时就确定下来
//s5直接引用常量池中的"疯狂Java"
String s5 = "疯" + "狂" + "Java";
//s6后面的字符串值不能在编译时就确定下来
//s6不能引用常量池中的字符串
String s6 = s2 + s3;
//使用new调用构造器将会创建一个新的String对象
//s7引用堆内存中新创建的String对象
String s7 = new String("疯狂Java");
//输出 true
System.out.println(s1 == s4);
//输出 true
System.out.println(s1 == s5);
//输出 false
System.out.println(s1 == s6);
//输出 false
System.out.println(s1 == s7);
}
}
例子中的s1,s4,s5所引用字符串可以在编译期就确定下来,因此它们都将引用常量池中的同一个字符串对象。
使用new String()
创建的字符串对象
是运行时创建出来的
,它被保存在运行时内存区(即堆内存)内
,不会放入常量池
中。
equals()
方法
-
equals()
方法是Object类
提供的一个实例方法,因此所有引用变量
都可调用该方法来判断是否与其他引用变量
相等。 equals()
方法判断两个对象相等的标准
与使用==运算符
没有区别,同样要求两个引用变量
指向同一个对象
才会返回true
。
- 因此这个
Object类
提供的equals()
方法没有太大的实际意义,如果希望采用自定义的相等标准
,则可采用重写equals()
方法来实现。
-
String
已经重写了Object类的equals()方法
,String的equals()
方法判断两个字符串相等的标准是:只要两个字符串所包含的字符序列
相同,通过equals()比较将返回true,否则将返回false。
通常正确地重写equals()方法
应该满足下列条件
- 自反性:对任意
x
,x.equals(x)
一定返回true
。 - 对称性:对任意
x
,y
, 如果y.equals(x)
返回true
,则x.equals(y)
也返回true
。 - 传递性:对任意
x
,y
,z
, 如果x.equals(y)
返回归true
,y.equals(z)
返回true
,则x.equals(z)
一定返回true
。 - 一致性:对任意
x
,y
, 如果对象中用于等价比较的信息没有改变,那么无论调用x.equals(y)
多少次,返回的结果应该保持一致,要么一直是true
,要么一直是false
。 - 对任何不是
null
的x
,x.equals(null)
一定返回false
。
总结
-
Object类
默认提供的equals()
只是比较对象的地址
,即Object类的equals()方法
比较的结果与==运算符
比较的结果完全相同。 - 在实际应用中常常需要重写
equals()方法
,重写equals()方法
时,相等条件
是由业务要求
决定的,因此equals()方法
的实现也是由业务要求
决定的。