文章目录
对象的4大特性
抽象
把现实生活中的某一类东西提取出来,用程序代码来表示,抽象出来的程序代码叫做类或接口。
抽象分为两个部分:数据(可以理解为现实事务的特征)抽象和行为抽象。
- 数据抽象:现实生活中事务的特征,对应类中的属性(比如现实生活中人有眼睛、鼻子等,抽象到类中就是眼睛属性、鼻子属性)。
- 行为抽象:现实生活中事务的行为,对应类中的方法(比如现实生活中人会吃饭、睡觉等,抽象到类中就是吃饭方法、睡觉方法)。
封装
把数据和行为集中到一个类中(用来提供给外部使用)。
继承
继承主要是为了实现代码的重用。父类中有一些属性和方法,子类继承父类,那么子类中也会有父类中的这些属性和方法。与此同时,子类也可以添加自己特有的属性,如果子类中方法的实现和父类不一样,子类也可以重写父类的方法。
多态
可以理解为不同对象同种行为的不同表现。在java中的表现为方法的重写、方法的重载以及动态绑定都为多态。
Object类中常见方法
object类是所有类的父类,里面有一些常用的方法。
equals()
我们知道所有的对象都拥有标识(内存地址)和状态(数据),同时“==”比较两个对象的的内存地址,所以说使用Object的equals()方法是比较两个对象的内存地址是否相等,即 object1.equals(object2)为true,则表示equals1和equals2实际上是引用同一个对象。
但如果我们不想在比较的时候比较两个对象的引用地址就需要重写equals方法。
hashCode()
hash值:Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。
为什么要重写hashcode()方法?其实当 equals 方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
我们是希望两个对象如果相等,那么在使用 hashSet 存储时也能认为这两个对象相等。
hashCode 是用于散列数据的快速存取,如利用 HashSet/HashMap/Hashtable 类来存储数据时,都会根据存储对象的 hashCode 值来进行判断是否相同的。
重写hashCode()和equals()
public class Student {
private String name; //姓名
private String sex; //性别
private String age; //年龄
private float weight; //体重
private String addr; //地址
// 重写hashcode方法
@Override
public int hashCode() {
int result = name.hashCode();
result = 17 * result + sex.hashCode();
result = 17 * result + age.hashCode();
return result;
}
// 重写equals方法
@Override
public boolean equals(Object obj) {
if(!(obj instanceof Student)) {
// instanceof 已经处理了obj = null的情况
return false;
}
Student stuObj = (Student) obj;
// 地址相等
if (this == stuObj) {
return true;
}
// 如果两个对象姓名、年龄、性别相等,我们认为两个对象相等
if (stuObj.name.equals(this.name) && stuObj.sex.equals(this.sex) && stuObj.age.equals(this.age)) {
return true;
} else {
return false;
}
}
}
clone()
public Person{
public String name;
public int age;
public Person(String name,int age){
this.name=name;
this.age=age;
}
}
Person p = new Person("张三",18);
Person p1 = p;
此时p1只是p的一个引用。
Person p = new Person("张三",18);
Person p1 = (Person)p.clone();
这么一调用之后就复制出了新对象。
浅拷贝
- 对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递。
- 对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递。
注意:String类型通过常量赋值时相当于基本数据类型,通过new关键字创建对象时便是引用数据类型
实现对象拷贝的类,需要实现 Cloneable 接口,并覆写 clone() 方法
public class Student implements Cloneable {
private String name;
private int age;
/**
* 重写clone()方法
* @return
*/
@Override
public Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
深拷贝
下面介绍一下基本深拷贝的代码 很短 : 你一定主要 主类包装了多少其他的引用类型的其他类,那么其他必须都要实现Cloneable 接口 以及clone 方法。
public class Student implements Cloneable {
public User user;
public Data data;
/**
* 重写clone()方法
* @return
*/
@Override
public Object clone() throws CloneNotSupportedException{
Student s=(Student)super.clone();
s.user=(User)user.clone();
s.data=(Data)data.clone();
return s;
}
}
finalize()
垃圾回收器准备释放内存的时候,会先调用finalize()。
内部类
普通内部类
public class Outer{
public class Inner{
}
}
- 内用外随意访问。
- 外用内,需要创建对象。
匿名内部类
接口名 inter=new 接口名(){
//覆写所有抽象方法
}
类的转型
向上转型
Animal cat = new Cat();
此时cat向上转型成Animal ,注意此时cat不能调用Cat类中独有的方法。
向下转型
类似于强制转换。
instanceof
当对象向上转型后如何判断他的向下转型的对象是什么呢,这就得用到instanceof
animal instanceof Dog
例子中的意思就是判断这个animal对象是不是dog类。