Java笔记(面向对象3)

Final

1.是什么

final 是修饰符,表示最终的,无法修改的

2.能做什么

  1. 修饰的变量不能二次赋值,一般叫常量(但是常量一般是psf的 public static final)
  2. 修饰的成员方法不能被覆写
  3. 修饰的类不能被继承

3.怎么用

//final int b=0;
final int b;
{
	b=1;
}
final static int c;
static {
	c=2;
} 
class A {
	public final void m1(){
	}
}
class B extends A{
//m1被final修饰无法覆写
//	@Override
//	public void m1(){}
	public void m2(){}
}
final class Sup{	
}
//被final修饰的类也无法被继承
//class Sub extends Sup{
//}

4.修饰引用类型

final Customer customer=new Customer(18);
//age属性没有被final修饰,所以可以被二次赋值
customer.age=20;
System.out.println(customer.age);
//customer被final修饰无法二次赋值
//customer=new Customer(12); 
class Customer{
	int age;
	Customer(int age) {
		this.age=age;
	}
}

多态

1.是什么

JVM四大特性:多线程、跨平台、自动垃圾回收、面向对象

面向对象特性:封装、继承、多态、抽象

多态:多态性,多形态,统一操作用于不同对象可以有不同的解释,产生不同的结果

父类引用指向子类对象 : 通过父类创建的引用类型变量,可以找到子类的对象

父类 变量名=new 子类();

能够使用父类的地方就一定可以使用子类(里氏替换原则)

2.相关知识

单一职责原则:

里氏替换原则:能够使用父类的地方就一定可以使用子类

依赖倒置原则:面向高层编程,底层应该依赖高层,而高层不依赖底层

接口隔离原则

迪米特法则

开闭原则

3.应用场景

多态应用场景

当一个需求对应多种不同实现的时候一定要使用多态

当一个需求只有一种实现的时候不需要使用多态

public static void main(String[] args) {
    User user=new User();
	user.test(new Cat());
    //Cat cat=new Cat();与上一行代码相同
    //user.test(cat);
	user.test(new Dog());
    class User {
		public void test(Animal animal){
			animal.eat();
		}
	}
	abstract class Animal{
		public abstract void eat();
	}
	class Cat extends Animal{
		@Override
		public void eat() {
			System.out.println("猫吃鱼");
		}
	}
	class Dog extends Animal{
		@Override
		public void eat() {
			System.out.println("狗吃肉");
		}
	}
}

4.优点

提高程序灵活性,扩展性,维护性,符合高内聚低耦合理念

5.缺点

丢失子类特有的属性(父类没有的,子类有,都属于子类特有,无法访问)

6.使用语法

通过多态进行调用:

  1. 父类没有的,都调用不了
  2. 父类有的,子类没有的,都执行父类
  3. 父类有,子类也有,除了成员方法执行子类,其他的都执行父类
Sup1 s1=new Sub1();
//父类有则可以调用
System.out.println(s1.a);
System.out.println(s1.b);
System.out.println(s1.c);
//父类中没有所以报错,不能调用
//System.out.println(s1.d);
//父类
s1.m1();
//子类 中只有成员方法执行,其他的都执行父类的
s1.m2();
class Sup1{
	int a =1;
	static int b =2;
	int c=3;//父类特有
	public static void m1(){
		System.out.println("父类静态");
	}
	public void m2(){
		System.out.println("父类成员");
	}
}
class Sub1 extends Sup1{
	int a=11;
	static int b=22;
	int d=4;
	public static void m1(){
		System.out.println("子类静态");
	}
	public void m2(){
		System.out.println("子类成员");
	}
}

7.Instanceof

多态发生在赋值的时候,不赋值不会发生多态

多态:又叫向上转型,子到父,类似自动类型转换

向下转型:父到子,类似强制类型转换

必须先向上转型,才能发生向下转型,父类转型不可能小于子类

//向上转型
Sup2 s=new Sub2();
//向下转型
Sub2 s3=(Sub2)s;
Sup2 s4=new Sup2();
// 下面运行会报错,因为没有发生向上转型,当强制转型为子类时,会出现错误
// java.lang.ClassCastException: Day11(包名).Sup2 cannot be cast to  Day11.Sub2
// 类型转换异常
// Sub2 sb2 = (Sub2) s4;
// 判断某个对象是否由某个类实例化而来
// 当true的时候,在进行向下转型,就可以避免类型转换异常
System.out.println(s4 instanceof Sub2);

8.多态的几种形式

//1.直接多态 父类 变量=new 子类();
Sup2 s2=new Sub2();
//2.形参实参多态 参数列表用父类声明,调用方法时传入子类对象
m21(new Sub2());
//3.返回值多态 返回值类型为父类类型 但是返回的值是子类对象
Sup2 i = m22();
public static Sup2 m22(){
	return new Sub2();
}
public static void m21(Sup2 s){
}

简单来说:只要是父类的引用类型变量保存的子类的对象就是多态

9.隐式多态

public class Poly_05 {
	public static void main(String[] args) {
		// SupClass sup = new SubClass();
		// System.out.println(sup.i);
		// sup.m2();
		SubClass sub = new SubClass();
		// System.out.println(sub.i);
		sub.m1();
		// sub.m2();
		// System.out.println(sub + "===");
	}
}
class SupClass {
	int i = 2;
	public void m1() {
		// System.out.println(this + "--------");
		// 这里的 this 会发生多态
		/**
		 * this 是当前对象中第一个成员变量,用于保存当前类对象的内存地址
		 * 
		 * 所以 this的类型可以为 当前类类型 或 父类类型 , 如果是父类类型,就是多态
		 * 
		 * 多态 丢失子类特有的属性
		 * 
		 * 但是this可以调用特有属性,所以 this的类型应该是 当前类类型 , 也就是 SupClass
		 * 
		 * SupClass this ;
		 * 
		 * this 出现在成员方法和构造方法中的时候, 谁调用的这个方法,this就指向谁
		 * 
		 * 由于是子类对象调用的m1,所以 this指向的是子类对象的内存地址
		 * 
		 * 得知 SupClass this = 子类对象;
		 */
		System.out.println(this.i);
		this.m2();
	}

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

class SubClass extends SupClass {
	int i = 22;

	public void m2() {
		System.out.println("子类m2");
	}
}

通过子类调用(未经覆写)父类的方法时,父类方法中的上下文环境就是多态环境

abstract

1.是什么

abstract 是修饰符,表示抽象

修饰的成员方法是抽象方法,并且没有方法体{}

修饰的类是抽象类,该种类不能创建对象

抽象方法必须在抽象类中,用于被子类覆写(或实现)

抽象类中可以没有抽象方法

abstract和final不能同时出现

如果一个类继承了一个抽象类,需要实现抽象类的所有的抽象方法

一个抽象类继承一个抽象类需要实现0~N个抽象方法,即可以一个也不实现

2.使用语法

//抽象类
abstract class C{
	{
		
	}
	static{
		
	}
    //普通类能写的抽象类也能写,只是可以额外写抽象方法
    //抽象类虽然不能创建对象,但是有构造方法,用于让子类创建对象是调用(构造方法第一行默认有super())
	//抽象方法
	public abstract void m11();
	//成员方法
	public void m12(){
		
	}
	//构造方法
	public C(){}
	//静态方法
	public static void m13(){}
}
class D extends C{
	@Override
	public void m11() {
		
	}
}
//抽象类继承抽象类,可以实现0~N个抽象方法
abstract class E extends C{
	
} 

3.应用场景

class Animal{
	public void eat(){
		System.out.println("动物吃东西");
	}
}

这里放在动物类中,只是规定了动物吃东西的功能,但是无法确定到底吃什么

class Cat extends Animal{
	@Override
	public void eat() {
		System.out.println("猫吃鱼");
	}
}
class Dog extends Animal{
	@Override
	public void eat() {
		System.out.println("狗吃肉");
	}
}

看到某个具体动物的时候我们才知道他吃什么

所以引入Animal类的目的是降低耦合度,又因为多态会丢失子类特有的属性,所以要在Animal类中添加动物吃东西的功能,然后又子类去覆写实现该功能,最后通过多态进行调用时,依然会执行子类覆写之后的方法

由此可见,Animal类只是进行功能定义,但是不包括功能实现,此时该方法应该定义为抽象方法,可以提醒子类进行覆写方法

abstract class Animal{
	public abstract void eat();
}
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值