前言:在咱大易途的第十三天,未来的路还很长,必须脚踏实地地把每天讲的内容多复习几遍,代码多敲几遍,不能好高骛远
基本数据类型不会继承Object类
clone()
Object类源码:protected native Object clone() throws CloneNotSupportedException;
这里有个问题:为什么Sun公司会用protected来修饰clone()方法呢,而不用public呢?有知道的朋友请指教
native表示该方法的实现不只是通过java实现的,还用C、C++实现
克隆一个对象的方法
1.先覆盖克隆方法
2.实现Cloneable接口
3.方法调用,抛出异常
-------------
public class ExecClone01{ //3.抛出异常
public static void main(String[] args) throws Exception{
Machine m1 = new Machine("Lenovo");
Machine m2 = m1.clone();
System.out.println(m1 == m2);//打印 false,说明克隆成功
System.out.println(m2.name);//打印 Lenovo
}
}
//2.实现Cloneable()接口
class Machine implements Cloneable{
String name;
public Machine(String name){
this.name = name;
}
//1.覆写clone()方法,抛出异常
@Override
public Machine clone() throws CloneNotSupportedException{//jdk5.0之后覆写的返回类型可以改变,但是必须是父类返回类型的子类类型->协变返回类型
Object obj = super.clone();
return (Machine)obj;
}
}
-------------
public class ExecClone02 { //3.方法调用的时候需要抛出异常
public static void main(String[] args) throws CloneNotSupportedException{
OS o1 = new OS("Win10");
OS o2 = o1.clone();
System.out.println(o1 == o2);
System.out.println(o2.name);
}
}
//要求OS类可以实现克隆
//2.实现一个接口:
Cloneableclass OS implements Cloneable{
String name;
public OS(String name){
this.name = name;
}
//1.先覆盖clone()方法 ->抛出异常CloneNotSupportedException
@Override
public OS clone() throws CloneNotSupportedException{
Object obj = super.clone();
return (OS)obj;
}
}
-------------
finalize()
protected void finalize() throws Throwable {}
对象的"遗言"方法
当gc回收一个对象的时候,主动会调用这个对象的finalize方法
面试题:final和finalize之间的区别?
final表示最终的 修饰符,可以修饰类、方法、变量
finalize是Object类里面的一个方法,当gc回收一个对象的时候会主动调用的一个方法
toString()
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
用来制定打印一个对象,显示的内容
当打印一个对象时,实际上打印的是该对象的toString方法,Object类本身打印对象,显示 类型@XX,String类中覆盖了Object类的toString方法,返回内容,所以打印出的是内容
-------------
public class Test01{
public static void main(String[] args){
Person p = new Person("王天二",22,'男',true);
System.out.println(p); //XXX先生/女士 今年XXX岁 是个已婚/未婚人士
}
}
class Person{
String name;
int age;
char gender;
boolean isMarry;
public Person(String name,int age,char gender,boolean isMarry){
this.name = name;
this.age = age;
this.gender = gender;
this.isMarry = isMarry;
}
@Override
public String toString(){//当要进行较多拼接时,最好是采用StringBuffer进行拼接,效率更高
return name + (gender == '男'?"男士":"女士") + " 今年" + age + "岁" + " 是个" + (isMarry?"已婚":"未婚") + "人士";
}
}
-------------
equals()
public boolean equals(Object obj) {
return (this == obj);
}
Object类本身比较的是两个对象的地址
程序员可以按照自己的意愿将内存里面不同的两个对象视为相等对象 -> 逻辑相等也就是说,制定一个类型比较的规则,当什么条件成立的时候,可以将两个不同的对象视为相等对象
Object类中equals()源代码如下:
//对象1.equals(对象2)
public boolean equals(Object obj){//普通方法,需要用对象来调用
//this:当前调用equals方法的对象
//obj:表示参数传来要参与比较的另一个对象
//==:比较地址
return (this == obj);
}
-------------
public class ExecEquals01 {
public static void main(String[] args){
Student stu1 = new Student("王天一",12,"A");
Student stu2 = new Student("陈浩南",24,"O");
Student stu3 = new Student("山鸡",25,"A");
System.out.println(stu1.equals(stu2)); //打印 false
System.out.println(stu1.equals(stu3)); //打印 true
}
}
/**
定义一个Student类型
属性:name age blood
创建对象时 完成所有属性的赋值
只要两个学生的血型一样就视为相等对象
*/
class Student{
String name;
int age;
String blood;
public Student(String name,int age,String blood){
this.name = name;
this.age = age;
this.blood = blood;
}
@Override
public boolean equals(Object obj){//覆写的条件 1.发生在有继承关系的子类中 2.权限修饰符大于父类被覆写方法权限修饰符;返回类型jdk5.0之前必须一致,jdk5.0之后可以是父类方法返回类型的子类类型,称为协变返回类型;方法签名(方法名和方法参数)必须一致 3.抛出异常的范围必须小于父类被覆写的方法抛出的异常
String blood1 = this.blood;
String blood2 = ((Student)obj).blood;
return blood1.equals(blood2);
}
}
-------------
public class ExecEquals02 {
public static void main(String[] args){
Food f1 = new Food("豆腐西施",12.5,"热菜");
Food f2 = new Food("西红柿炒鸡蛋",12.5,"热菜");
Food f3 = new Food("豆腐西施",12.5,"热菜");
System.out.println(f1.equals(f2));
System.out.println(f1.equals(f3));
}
}
/**
定义一个Food类型
属性:name price type
两个菜的所有属性一样就视为两个对象相等
考虑一行实现
*/
class Food{
String name;
double price;
String type;
public Food(String name,double price,String type){
this.name = name;
this.price = price;
this.type = type;
}
@Override
public boolean equals(Object obj){
return (this.name).equals(((Food)obj).name) &&
(this.price == ((Food)obj).price) &&
(this.type.equals(((Food)obj).type));
}
}
-------------
hashCode()
public native int hashCode();
制定一个对象的散列特征码
散列:将一大组数据分散为不同的小组
HashSet HashMap的底层是基于哈希表实现的
比如:将19 5 62 81 93 66分为4组,可以将每个数对4取余 x%4
[0]
[1]93 81 5
[2]66 62
[3]19
注意:当equals()方法被重写时,通常有必要重写hashCode()方法,以维护
hashCode()方法的常规协定,该协定声明相等对象必须具有相等的哈希码
----------
public class Test04 {
public static void main(String[] args){
Teacher tea1 = new Teacher("二爷",10000.0,'女',true);
Teacher tea2 = new Teacher("二爷",1232,'女',false);
Teacher tea3 = new Teacher("二爷",10000.0,'女',true);
System.out.println(tea1.equals(tea2)); //打印 false
System.out.println(tea1.equals(tea3)); //打印 true
System.out.println(tea1.hashCode()); //打印 685487
System.out.println(tea2.hashCode()); //打印 676718
System.out.println(tea3.hashCode()); //打印 685487
}
}
class Teacher{
String name;
double salary;
char gender;
boolean isMarry;
public Teacher(String name,double salary,char gender, boolean isMarry){
this.name = name;
this.salary = salary;
this.gender = gender;
this.isMarry = isMarry;
}
@Override
public boolean equals(Object obj){
if(obj == null)return false;
if(!(obj instanceof Teacher))return false;
if(obj == this)return true;
return this.name.equals(((Teacher)obj).name)&&
this.salary == (((Teacher)obj).salary)&&
this.gender == (((Teacher)obj).gender)&&
this.isMarry == (((Teacher)obj).isMarry);
}
@Override
public int hashCode(){
return name.hashCode() + (int)salary + gender + (isMarry?1:0);
}
}
-----------