目录
一、Object类
Object是所有的类的父类,不需要声明,所有对象都可以由Object来接收(包括自己新建的类),可以复写Object中的类。
1、equals方法的复写
“==”进行的是两个变量数值的比较,对于基本数据类型来说比较的就是基本数值是否相等,对于引用数据类型来说比较的是两个引用是否指向同一个对象(即地址是否相同)。
equals方法进行的是两个类对象的属性值比较,若类的对象需要具体比较属性值是否相等需要复写Object类中提供的equals方法。
public class ObjectTest {
public static void main(String[] args) {
Person person = new Person("洋洋",22);
Person person1 = new Person("洋洋",22);
System.out.println(person==person1);
System.out.println(person.equals(person1));
}
}
class Person{
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if(this==obj){
return true;
}
if(obj ==null || !(obj instanceof Person)){
return false;
}
Person obj1 = (Person) obj;
if(this.age==obj1.age&&this.name.equals(obj1.name)){
return true;
}
return false;
}
}
在Person类中重写了Object类的equals方法,使该方法能比较对象的属性值。在方法中this.name.equals(obj1.name)并不是递归,this.name是String类型。String类中的equals方法系统已经重写可以直接调用。
包装类,String类和集合类的equals的复写已经在系统中实现可以直接调用。
2、使用java.util.Comparator<T>接口
要比较的类本身并不实现这个接口,实现Comparator接口的类就表示作为该类的比较器。
将要比较的类和具体的比较“策略”解耦思想=>策略模式。
如果需要进行按照成绩的生序排序则传入升序的比较器。
若需要按照成绩降序排序,传入降序的比较器。
比较器都是不同的对象,和要比较的类入Student类是不同的类。
class Student {
private String name;
private int age;
private int score;
public Student(String name, int age, int score) {
this.name = name;
this.age = age;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
public int getScore() {
return score;
}
}
class StudentSec implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o1.getScore() - o2.getScore();
}
}
class StudentDesc implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
return o2.getScore() - o1.getScore();
}
}
public static void main(String[] args) {
Student s1 = new Student("佳佳", 22, 70);
Student s2 = new Student("洋洋", 24, 66);
Student s3 = new Student("达达", 18, 80);
Student s4 = new Student("小昱", 24, 90);
Student[] students = new Student[]{s1,s2,s3,s4};
Arrays.sort(students,new StudentDesc());
System.out.println(Arrays.toString(students));
Arrays.sort(students,new StudentSec());
System.out.println(Arrays.toString(students));
}
二、包装类
JDK中的包装类分为两种:
Object的直接子类,char的包装类Character和boolean的包装类Boolean。
Number的直接子类,整型byte(Byte)、short(Short)、int(Integer)、long(Long)和浮点型float(Float)、double(Double)
1、包装类和基本类型的相互转换
(1)基本类型->包装类对象
成为装箱,通过相应包装类的构造方法或者valueOf方法。
(2)包装类对象->基本类型
成为拆箱。调用相应包装类的xxValue方法实现拆箱。
(3)转换的实现
public static void main(String[] args) {
int a = 10;
Integer i1 = Integer.valueOf(a);
int b = i1.intValue();
System.out.println(b+1);
}
任何一个数值型包装类都具有以下这六个方法的实现,可以方便将某个类型转为任意其他类型。
包装箱的装箱和拆箱解决了将基本类型封装到类之中的问题,这就引入了一个新的问题,若需要进行基本类型的运算,需要来回装箱和拆箱很麻烦,所以在JDK编译阶段引入自动拆装箱。
public static void main(String[] args) {
int a = 10;
int ret = a+1;
System.out.println(ret);
Integer i1 = 10;
Integer ret1 = i1+1;
System.out.println(ret1);
}
有了自动拆装箱后,使用包装类和使用基本类型用法上没什么区别。阿里编码规范:对于基本的POJO类(自定义类),成员变量统一使用包装类,方法中的局部变量可以使用基本类型。
基本类型和包装类本质上是两个不同的类型,包装类的本职还是类,对于类来说,默认值null。基本类型的默认值就是各个数据类型的默认值。
2、包装类的缓存问题
包装类仍然是类,要比较属性值是否相等用equals,不能用==。
public static void main(String[] args) {
Integer a = 111;
Integer b = 111;
Integer c = 130;
Integer d = 130;
System.out.println(a==b);
System.out.println(a.equals(b));
System.out.println(c==d);
System.out.println(c.equals(d));
}
==比较的仍然是地址,equals比较的是属性值。
而数值型包装类都会在内部有缓存池。Integer默认缓存-128~127的数值,当第一次装箱时,该数值在缓存池中没有新的对象,产生该对象置入缓存池,若有下一次又有了该数值的装箱,不会产生新的包装类对象,直接将缓存对象返回。所以第一