第十五章 常用类
1.作业回顾
编写一个比较器AreaComparator比较实现了Areable接口的任意图形的面积,Circle,Rectangle等等。
编写一个测试类AreaComparatorTest来测试任意图形面积的比较结果。
public interface Areable {
double getArea();
}
class Rectangle implements Areable{
private double x;
private double y;
public Rectangle(double x, double y) {
super();
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double getArea() {
return x * y;
}
}
class Circle implements Areable{
private double r;
public Circle(double r) {
super();
this.r = r;
}
public double getR() {
return r;
}
public void setR(double r) {
this.r = r;
}
public double getArea() {
return r * r * Math.PI;
}
}
public class AreaComparator {
public int compare(Areable a1, Areable a2) {
if(a1.getArea() > a2.getArea()) {
return 1;
}else if(a1.getArea() < a2.getArea()){
return -1;
}else {
return 0;
}
}
}
public class AreaComparatorTest {
public static void main(String[] args) {
Areable a1 = new Circle(2.5);
Areable a2 = new Rectangle(2.0, 3.0);
int result = new AreaComparator().compare(a1, a2);
System.out.println(result);//1
}
}
2.Object类
2.1 toString方法
java中所有的类都直接或间接的继承于Object类,自动拥有Object类的所有方法。
toString方法用于输出一个对象的内容。
class Animal{
private String name;
private String type;
public Animal(String name, String type) {
super();
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Animal [name=" + name + ", type=" + type + "]";
}
}
public final class Day1502 {
public static void main(String[] args) {
Animal a1 = new Animal("旺财", "中华田园犬");
//Animal类继承Object类,因此继承了toString方法
//toString方法用于将对象的内容转换为String
//Object类的toString方法将返回对象所属的类以及哈希码
//可以重写toString方法,以获得格式化的对象的内容
String str = a1.toString();
//day15.Animal@53bd815b
//Animal [name=旺财, type=中华田园犬]
System.err.println(str);
//Animal [name=旺财, type=中华田园犬]
//System.out.println(object x)内部会调用对象的toString方法
System.out.println(a1);
}
}
2.2 equals方法
Object类的equals方法用于比较两个对象的地址是否相等.
Object类的equals方法是使用==来比较。==比较的是对象的引用是否相等.
可以重写equals方法来比较对象的属性是否相等。
class Client{
private int id;
public Client(int id) {
super();
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
//如果重写了equlas方法,那么也应该重写hashCode方法,从而保证相同的对象的哈希码也相同。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + id;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Client other = (Client) obj;
if (id != other.id)
return false;
return true;
}
}
public class Day1503 {
public static void main(String[] args) {
Client c1 = new Client(25);
Client c2 = new Client(25);
//在对象之间使用==比较的是对象的地址是否相同
System.out.println(c1 == c2);//false
//使用从Object类继承来的equals方法来比较对象是否相等
//Object类的equals方法内部比较的是对象的地址, false
//可以重写equals方法来比较对象的属性, true
System.out.println(c1.equals(c2));//false,true
// Client c3 = null;
//在一个null对象上调用方法会导致NullPointerException
// c3.equals(c1);
}
}
2.3 hashCode方法
Object类的hashCode方法将返回对象的哈希码,哈希码是一个整数值,这个数值跟对象的内容有直接关系。
Object类的hashCode方法简单的使用对象的内存地址作为哈希码,但是并不符合hashCode方法的意义。
哈希码是对于对象的属性使用hash算法得到的一个整数值。这个整数值相当于对象的摘要。相同对象的哈希码总是相同的,不同对象的哈希码也可能相同。
可以重写hashCode方法,以保证hashCode方法的意义。如果重写了equlas方法,那么也应该重写hashCode方法,从而保证相同的对象的哈希码也相同。
hashCode方法应用于集合中的数据结构:哈希表。如果要将对象放入哈希表中,那么必须重写equals和hashCode方法。
class Animal{
private String name;
private String type;
public Animal(String name, String type) {
super();
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public String toString() {
return "Animal [name=" + name + ", type=" + type + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((type == null) ? 0 : type.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;
Animal other = (Animal) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (type == null) {
if (other.type != null)
return false;
} else if (!type.equals(other.type))
return false;
return true;
}
}
public class Day1504 {
public static void main(String[] args) {
Animal a1 = new Animal("旺财", "Dog");
Animal a2 = new Animal("多啦A梦", "Cat");
System.out.println(a1.hashCode());//26277749
System.out.println(a2.hashCode());//242929798
}
}
3.包装类
包装类将基本类型的值包装成一个对象。
基本数据类型:boolean,byte, char , double, float, int , long, short
包装类: Boolean,Byte,Character,Double, Float, Integer,Long,Short
包装类对象有一个基本类型的属性用于保存基本类型的数据。
使用构造方法创建包装类对象:
public class Day1505 {
public static void main(String[] args) {
//创建了一个Integer类的对象,它所保存的数据是10
//Integer类的对象的值是不可变的
Integer i = new Integer(10);
Boolean b = new Boolean(true);
Byte by = new Byte((byte) 10);
Short s = new Short((short) 12);
Character c = new Character('C');
Long l = new Long(100L);
Float f = new Float(55.0f);
Double d = new Double(55.0);
}
}
3.1 使用包装类的原因
1,基本数据类型不允许null值,使用包装类可以。
2,集合中不允许使用基本数据类型,可以使用包装类。
3,类型转换。
public class Day1506 {
public static void main(String[] args) {
//对象变量i为空,说明i不引用任何对象
Integer i = null;
int a = 10;
//基本数据类型需要类型转换
short s = (short) a;
System.out.println(s);//10
i = new Integer(10);
//包装类不需要类型转换
//获取short值
short ss = i.shortValue();
System.out.println(ss);//10
}
}
3.2 valueOf方法
valueOf方法替代构造器,提供了另外一种方式创建包装类对象。
valueOf方法将基本类型的值变成一个包装类对象。
public class Day1507 {
public static void main(String[] args) {
//所有基本类型的包装类都有valueOf方法
//以Integer举例
Integer i1 = new Integer(10);
Integer i2 = Integer.valueOf(10);
Integer i3 = Integer.valueOf("10");
Integer i4 = Integer.valueOf("1010", 2);
System.out.println(i1);//10
System.out.println(i2);//10
System.out.println(i3);//10
System.out.println(i4);//10
}
}
3.3 xxxValue方法
xxxValue方法,可以将包装类对象变成基本类型的值。
public class Day1508 {
public static void main(String[] args) {
//所有包装类对象都有xxxvalueOf方法
//以Integer举例
Integer i1 = Integer.valueOf(10);
int i2 = i1.intValue(); //intvalue返回对象的int值
float i3 = i1.floatValue();//floatvalue返回对象的float值
//本该输出对象的地址,这里i1输出了对象的内容,因为Integer类重写了toString方法
System.out.println(i1);//10
System.out.println(i2);//10
System.out.println(i3);//10.0
Long.valueOf(10L).intValue();
}
}
3.4 静态的toString方法
静态的toString方法,将基本数据类型转换为字符串
public class Day1510 {
public static void main(String[] args) {
String str1 = Integer.toString(10);
System.out.println(str1);//10
//将10转换成二进制字符串
String str2 = Integer.toString(10, 2);
System.out.println(str2);//1010
System.out.println(Integer.toBinaryString(10));//十进制转二进制,1010
System.out.println(Integer.toOctalString(10));//十进制转八进制,12
System.out.println(Integer.toHexString(10));//十进制转十六进制,a
System.out.println(Integer.valueOf("1010", 2));//10
System.out.println(Integer.valueOf("12", 8));//10
System.out.println(Integer.valueOf("a", 16));//10
}
}
4.自动装箱和自动拆箱
public class Day1511 {
public static void main(String[] args) {
//自动装箱,将1包装成一个Integer对象,然后将地址赋值给i1
//编译后,调用类方法Integer.valueOf(int i);
//相当于Integer i1 = integer.valueOf(1);
Integer i1 = 1;
//自动拆箱,取出i1引用对象的值,然后赋值给i2
//编译后,调用实例方法i1.intValue();
//相当于int i2 = i1.intValue();
int i2 = i1;
//本该输出对象的地址,这里i1输出了对象的内容,因为Integer类重写了toString方法
System.out.println(i1);//1
System.out.println(i2);//1
Integer ten = new Integer(10);
ten++;//先自动拆箱,运算,再自动装箱
}
}
public class Day1512 {
public static void f1(Integer i) {
System.out.println(i);//2
}
public static void f2(int i) {
System.out.println(i);//2
}
public static void main(String[] args) {
f1(2);//自动装箱
f2(new Integer(2));//自动拆箱
}
}
5.包装类的缓存
public class Day1513 {
public static void main(String[] args) {
Integer nineA = new Integer(9);
Integer nineB = new Integer(9);
System.out.println(nineA == nineB);//false
//Integer重写了equals方法,比较对象的内容
System.out.println(nineA.equals(nineB));//true
Integer i1 = 9;//自动装箱,Integer i1 = Integer.valueOf(9);
Integer i2 = 9;//自动装箱,Integer i2 = Integer.valueOf(9);
//使用Integer.valueOf(int i)方法,如果字面值是-128~127,就会从缓存中获取一个对象(共256个对象)
System.out.println(i1 == i2);//true ==比较的是地址
System.out.println(i1.equals(i2));//true equals比较的是内容
Integer i3 = 128;//自动装箱,Integer i3 = Integer.valueOf(128);
Integer i4 = 128;//自动装箱,Integer i4 = Integer.valueOf(128);
System.out.println(i3 == i4);//false
System.out.println(i3.equals(i4));//true
}
}
6.练习
1,创建一个类Student,属性int id,String name,char gender,int age,重写toString方法,重写hashCode和equals方法。创建两个对象,使用equals方法比较两个对象是否相等。
2,将二进制数1001000111110101,转换为十六进制数和八进制数并输出。