getClass()方法-复习
getClass获取一个类的运行时对象,Class对象,类对象
这个方法仅用来获取对象,这个Class对象是类加载时JVM在堆上创建的
类加载只有一次,所以对于一个类来说,Class对象也只有一份,所以只要是同一个类生成的对象,那么他们的Class对象就是同一个(地址值相同)
Class对象有啥用?
用来获取类型信息;包括有哪些成员变量、有哪些方法、有哪些构造器等
Class对象是反射的基础
反射是可以为所欲为的,反射实际上就是Class API
4* > Class类的常用API
* - getName()
* - 获取类的全限定类名
* - getSimpleName()
* - 获取类名
instanceof和get.Class比较
这里涉及排他性的问题,就是在重写equals方法时候的两种比较方式具体的话改日单独拿出来写写文章。
hashCode()方法
哈希冲突
hashCode方法和equals方法的联系
hashCode方法重写
使用idea快捷键
finalize方法—再java1.9中已经去除,可以不掌握
借鉴了c++中的析构函数,析构函数是给对象的死亡做善后工作的
clone()方法
clone方法:
* 1,会得到一个完全独立的对象
* 2,这个独立的对象会和原先的对象具有相同的成员变量取值
对于受保护的访问权限如果想在不同包下使用,需要在子类中创建子类自身对象去访问。重写的方法访问权限至少和原有的访问权限保持一致,只能更宽松。
受保护的访问权限在同包下是可以随意访问的
这里需要注意Cloneable是一个空接口,那么空接口的作用这里需要一段代码来说明
只有实现这个空接口才能进行接下来的操作。
public class Demo { public static void main(String[] args) { judge(new A()); judge(new B()); } public static void judge(Object obj){ if (obj instanceof EmptyInterface){ //这里表示e指向的对象是空接口的实现子类对象 System.out.println("e实现了空接口"); } else{ System.out.println("e未实现空接口"); } } } interface EmptyInterface{ } class A implements EmptyInterface{ } class B{ }
在这里说一个“父 子 孙”的问题,在这里都实现了空接口
public class Demo7 { public static void main(String[] args) { judge(new A()); judge(new B()); } public static void judge(Object obj){ if (obj instanceof EmptyInterface){ //这里表示e指向的对象是空接口的实现子类对象 System.out.println("e实现了空接口"); } else{ System.out.println("e未实现空接口"); } } } interface EmptyInterface{ } class A implements EmptyInterface{ } interface Son extends EmptyInterface{} class B implements Son{ }
好了,我们到此就解决了访问权限和空接口的问题,接下来就可以使用clone操作了
clone的基本操作,这里的内存地址不一样 内容是一样的,代码如下所示:
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Student s = new Student(18,52);
Object clone = s.clone();
Student cloneStu = (Student) clone;
System.out.println(s);
System.out.println(cloneStu);
}
}
class Student implements CloneableSon{
int age;
double score;
public Student() {
}
public Student(int age, double score) {
this.age = age;
this.score = score;
}
//重写toString方法
@Override
public String toString() {
return "Student{" +
"age=" + age +
", score=" + score +
'}';
}
//重写clone方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
//接口之间是可以继承的
interface CloneableSon extends Cloneable{
}
8-根据实际情况修改返回值类型,修改成Object的子类
9-重写clone方法的规则,通常不需要重写
clone() 方法对该副本的要求:
对于任何对象 x,表达式:
1,x.clone() != x 为 true(这一条是必须的) //克隆后的对象不能还是原先对象
2,x.clone().getClass() == x.getClass() 为true //克隆后的类型不能改变
3,x.clone().equals(x) 为true(一般情况下为true,但这并不是必须要满足的要求)
10-浅克隆
代码表现如下:
这里是浅克隆,并未拷贝公用对象
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Student s = new Student(18,52,new Cat(3));
/*Object clone = s.clone();
Student cloneStu = (Student) clone;
*/
// Student cloneStu = s.clone();
// System.out.println(s);
// System.out.println(cloneStu);
Student cloneStu = s.clone();
System.out.println(s);
System.out.println(cloneStu);
cloneStu.c.age = 1000;
System.out.println(s);
System.out.println(cloneStu);
}
}
class Student implements CloneableSon{
int age;
double score;
Cat c;
public Student() {
}
public Student(int age, double score) {
System.out.println("构造器执行了");
this.age = age;
this.score = score;
}
//三参的构造器
public Student(int age, double score, Cat c) {
this.age = age;
this.score = score;
this.c = c;
}
//重写toString方法
@Override
public String toString() {
return "Student{" +
"age=" + age +
", score=" + score +
", c=" + c +
'}';
}
//重写clone方法
@Override
protected Student clone() throws CloneNotSupportedException {
return ((Student) super.clone()) ;
}
}
//接口之间是可以继承的
interface CloneableSon extends Cloneable{
}
class Cat{
int age;
public Cat() {
}
public Cat(int age) {
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"age=" + age +
'}';
}
}
深克隆代码体现如下:
public class Demo {
public static void main(String[] args) throws CloneNotSupportedException {
Student s = new Student(18,52,new Cat(3));
/*Object clone = s.clone();
Student cloneStu = (Student) clone;
*/
// Student cloneStu = s.clone();
// System.out.println(s);
// System.out.println(cloneStu);
Student cloneStu = s.clone();
System.out.println(s);
System.out.println(cloneStu);
cloneStu.c.age = 1000;
System.out.println(s);
System.out.println(cloneStu);
}
}
class Student implements CloneableSon{
int age;
double score;
Cat c;
public Student() {
}
public Student(int age, double score) {
System.out.println("构造器执行了");
this.age = age;
this.score = score;
}
//三参的构造器
public Student(int age, double score, Cat c) {
this.age = age;
this.score = score;
this.c = c;
}
//重写toString方法
@Override
public String toString() {
return "Student{" +
"age=" + age +
", score=" + score +
", c=" + c +
'}';
}
//重写clone方法
@Override
protected Student clone() throws CloneNotSupportedException {
// return ((Student) super.clone()) ;
// 深克隆实在浅克隆的基础上实现的
Student cloneStu = (Student) super.clone();
// 接下来克隆一份Cat对象,这里也需要在Cat类中重写Clone方法,因为clone是受保护的,这样可以有权限了;接下来实现空接口
//用哪个引用做克隆操作,两个都可以,用哪个看你心情
//this.c.clone()
Cat cloneCat = cloneStu.c.clone();
//让克隆对象的克隆c引用指向克隆的Cat对象
cloneStu.c = cloneCat;
return cloneStu;
}
}
//接口之间是可以继承的
interface CloneableSon extends Cloneable{
}
class Cat implements Cloneable{
int age;
public Cat() {
}
public Cat(int age) {
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"age=" + age +
'}';
}
@Override
protected Cat clone() throws CloneNotSupportedException {
return ((Cat)super.clone());
}
}
致歉
本人排版功力尚浅、这是听课的笔记以及课下自己草草整理,所以很多地方可能排版可能会出现乱的情况。作为一个合格的Coder应该以逻辑严密、文档代码干净整洁为目标。我会在接下来的笔记里体现出来,对于自己笔记之前的不严密在这里向诸位读者道歉。