覆写、final、多态

Day10 覆写、final、多态

  1. 面向对象
    1.1 覆写
    1.1.1 是什么
    覆写就是子类和父类有个一样(方法名,参数列表,返回值都一样)的成员方法
    覆写特指成员方法,只有成员方法可以覆写
    1.1.2 应用场景
    什么时候需要覆写 :
    如果父类方法不能满足子类需求的时候,需要对方法进行覆写

覆写条件:
1 必须是有继承关系
2 方法名,参数列表,返回值 必须相同
3 不能拥有更低访问权限
4 不能有更宽泛的异常

继承最基本的作用 : 代码重用
继承最重要的功能 : 方法覆写
1.1.3 覆写目的
覆写目的 :
1 满足当前需求
2 错误越来越少
3 使用范围越来越广
4 功能越来越强
1.1.4 覆写案例

public static void main(String[] args) {
Cat cat = new Cat();
cat.move();

	Dog dog = new Dog();
	dog.move();
}

}
class Animal{
public void move(){
System.out.println(“动物在移动”);
}
}
class Cat extends Animal {
// 不能满足子类需求,进行重写
public void move() {
System.out.println(“猫在走猫步”);
}
}
class Dog extends Animal {
// 不能满足子类需求,进行重写
public void move() {
System.out.println(“狗在爬”);
}
1.2 Final
1.2.1 是什么
final 是修饰符,表示最终的,不能更改的
1.2.2 能干什么
1、final 修饰的类 不能被继承
2、final 修饰的成员方法 不能被覆写
3、final 修饰的变量 没有默认值,必须显示赋值,并且整个生命周期中值不可更改
4、常量 一般写为 : public static final , 常量命名 建议全部大写
1.2.2.1 修饰类
final class A{

}
class B extends A{

}

1.2.2.2 修饰方法

1.2.2.3 修饰变量

1.2.3 易错点

案例代码如下:
public static void main(String[] args) {
// final修饰的引用类型,user变量的值不能更改
final User user = new User(22);
// 和user引用指向的堆内存空间中的数据没有关系
// 因为age又没有加final修饰
user.age = 24;
user.age = 55;
// 引用user使用final修饰,所以不能更改user变量的值
// user = null;
System.out.println(user.age);
}
}

class User {
int age;

public User(int age) {
	super();
	this.age = age;
}

1.3 多态
1.3.1 软件设计六大原则
http://baijiahao.baidu.com/s?id=1645013441658118287&wfr=spider&for=pc

单一职责原则
里氏替换原则 : 能使用父类的地方就一定可以使用子类
依赖倒置原则
接口隔离原则
迪米特原则
开闭原则

1.3.2 是什么
什么是多态 : 父类引用指向子类对象
父类引用 : 使用父类类型创建的引用类型变量
指向 : 通过这个引用类型变量,可以找到哪个对象
子类对象 : 创建的子类对象
语法:
父类 变量 = new 子类();
java中提供了两种多态机制
1 编译时多态
编译时多态是静态的,主要指方法重载,根据不同参数列表来区分不同的方法,编译之后也会形成不同的两个方法
运行时调用该方法的时候,就算多态了,因为调用的是两个方法
2 运行时多态
运行时多态是动态的,主要是动态绑定来实现的,主要靠子类实现的父类的方法来完成,这就是多态性

1.3.3 多态的几种形式
多态的几种形式
1 直接变量 发生多态
父类 变量 = new 子类()
2 实参/形参
方法声明的时候,参数列表用父类声明,而调用方法的时候 传递子类对象
public static void m1(Sup s){}
m1( new Sub() );
3 返回值
返回值类型写的是父类,而具体返回的时候却返回子类对象
public Sup m1(){
return new Sub();
}

多态缺点 : 丢失子类特有的属性
案例如下:
public static void main(String[] args) {
// 直接多态
Sup s1 = new Sub();

	// 实参/形参多态
	Sub sub = new Sub();
	m1(sub);

	// 返回值多态
	Sup sup = m2();
}

public static void m1(Sup s) {
	// s 发生多态
}

public static Sup m2() {
	return new Sub();
}

1.3.4 多态属性调用
使用多态进行属性调用 :
1 父类没有,报错,而且是编译时报错
2 父类有,子类没有,执行父类
3 父类有,子类也有 , 除了成员方法执行子类,其他都执行父类
1.3.5 Instanceof
多态又叫向上转型 , 子类到父类是自动转换
父类到子类,是强制转换,又叫向下转型(必须先发生向上转型,再发生向下转型)

案例代码如下
public static void move(Animal a) {
// instanceof : 判断某个对象是否由某个类实例化而来
// 直接 类型转换 容易造成 错误 java.lang.ClassCastException
// Cat c = (Cat) a;
if (a instanceof Cat) {
Cat c = (Cat) a;
c.move();
} else if (a instanceof Dog) {
Dog d = (Dog) a;
d.move();
}
}

1.3.6 隐秘多态
案例如下:
this 发生多态
this : 是成员变量,保存当前类对象的内存地址,并且谁调用的该方法,this就是谁
this 用来保存当前对象的内存地址,那么this一定有数据类型
1 当前类类型
2 父类类型(多态)
因为this可以调用当前类中的所有属性,所以一定不是父类类型,因为多态会丢失子类特有的属性
所以this一定是当前类类型(this所在的类,就是当前类)
而 this出现在 Sup1中, 所以就等于 Sup1 this;
谁调用该方法,this就是谁,但是因为继承关系,是通过子类对象调用的m1方法,所以this指向子类对象
Sup1 this = new Sub1();

总结 : 通过子类对象调用父类的方法的时候,父类这个方法的上下文环境就是多态环境
public class Poly_04 {

public static void main(String[] args) {
	Sub1 sub = new Sub1();
	sub.m1();
	System.out.println(sub);
}

}

class Sup1 {
int i = 13;
static int age = 1;

public void m1() {
	System.out.println(i);
	System.out.println(age);
	m2();
}

public void m2() {
	System.out.println("父类的M2");
}

}

class Sub1 extends Sup1 {
int i = 52;
static int age = 12;

public void m2() {
	System.out.println(i);
	System.out.println(super.i);
	System.out.println("子类的M2");
}

}

1.4 Object
1.4.1 是什么
Object是java提供的根类,所有类都要直接或者间接继承Object
意味着 Object中的方法,是所有类都有的
Object在java.lang.Object 所以 使用不需要导包

getClass : 获取运行时类,反射机制讲解
Clone : 克隆对象,废弃
Notify,notifyAll,wait : 让线程进入等待,和唤醒线程,多线程讲解

toString,finalize,equals,hashCode(散列表讲解)
1.4.2 Equals
Equals : 设计目的 是比较两个对象是否相等
== : 基本类型比较值,引用类型比较地址,
我们比较引用类型的时候不会比较地址,因为不同对象的地址一定是不同的
除非你就想比较地址(没有任何价值)
两个对象进行比较的时候,肯定是用有价值的属性进行比较,所以不会使用 == ,而是使用equals
而 默认的Object中的equals方法,比较内存地址
public boolean equals (Object obj){ return this == obj; }
因为默认不知道比较什么属性,所以默认比较内存地址,根据自己的需求 进行方法重写即可
不同类没有可比性
并且 任何引用类型比较都需要转换为基本类型比较

覆写案例如下
public boolean equals(Object obj) {
// 1 先比较内存地址
if (this == obj) {
return true;
}
// 2 判断是否是同类
if (obj instanceof Student) {
Student s1 = (Student)obj;
if (this.id == s1.id && this.name.equals(s1.name)) {
return true;
}
}
return false;
}
1.4.3 Finalize
JVM四大特性 :
跨平台,面向对象,多线程,自动垃圾回收机制

当没有更多引用指向该对象的时候,此时该对象被视为垃圾数据
Object中的finalize方法,是当对象被回收之前,自动调用该方法
1 finalize方法所有对象都有
2 finalize方法不需要程序员调用,由系统自动调用
3 就算程序员对finalize方法进行调用,也只是单纯的方法调用而已,并没有垃圾回收功能
4 因为finalize方法并不会垃圾回收,而且被回收之前,自动执行一次而已
5 结合finalize方法的执行特征,可以在对象销毁之前,做一些关闭资源等销毁操作
public static void main(String[] args) {
Finalize_01 f = new Finalize_01();
f = null;
// 垃圾多了,自动回收
// for (int i = 0; i < 9999999; i++) {
// new Finalize_01();
// }

	// 程序员也可以 建议 自动回收,建议可以不听
	System.gc();
}

@Override
protected void finalize() {
	System.out.println(this+" 垃圾以回收");
}

1.4.4 HashCode
hashCode : 设计目的 ,是为了给每个对象生成一个唯一的标识符
同一个对象,生成多次,一定是相同的值,但是不同的对象生成多次,也有可能生成相同的值,哈希冲突
hashCode方法是根据hash算法得到的哈希值
hash算法 : 是一种安全的加密算法,把不定长的值,转换为定长的值,并不能保证其唯一性
算法 :
直接寻址法 , 数字分析法,平方取中法,折叠法,随机数法,除留余数法
覆写案例如下:
@Override
public int hashCode() {
return 11;
}
public static void main(String[] args) {
HashCode_01 ha = new HashCode_01();
HashCode_01 ha1 = new HashCode_01();
System.out.println(ha);
System.out.println(ha1);
// 得到十进制的值
System.out.println(ha.hashCode());
// Integer.toHexString 转换为十六进制显示
System.out.println(Integer.toHexString(ha.hashCode()));
}
1.4.5 toString
toString设计目的 : 返回该对象的字符串形式
Object中的toString方法 默认返回内存地址
当我们输出一个 引用类型对象的时候 会自动调用该对象的toString方法
语法
public String toString() {
return getClass().getName() + “@” + Integer.toHexString(hashCode());
}

覆写案例如下:
public class ToString_01 {

public static void main(String[] args) {
	User u = new User(17,"张三");
	System.out.println(u);
}

}
class User{
int age;
String name;

public User(int age, String name) {
	super();
	this.age = age;
	this.name = name;
}

@Override
public String toString() {
	return "年龄:"+age+",姓名:"+name;
}

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值