第八天内容

面向对象

接口

接口的关系

类和类之间是继承关系,不支持多继承,可以多层继承.

类和接口之间是实现关系,支持多实现,类可以多实现接口.

接口和接口之间的关系是继承,接口之间支持多继承关系.

interface B{}
interface C{}
interface A extends B,C{}
/*
 *  D类,实现接口A
 *  A接口,继承了B和C
 *  D类重写A,B,C 三个接口的全部抽象方法
 */
public class D implements A {

	@Override
	public void interB() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void interC() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void interA() {
		// TODO Auto-generated method stub
	}
}

接口的实现类还是抽象类

定义实现类实现了接口, 但是只重写了一部分的抽象方法,这个实现类还是抽象类.

 interface A{
     public abstract void function1(); 
     public abstract void function2(); 
 }

 abstract class B implements A{
     public void function1(){
         
     }
 }

抽象类和接口的区别

  • 从定义上看
    • 接口定义关键字 interface
    • 抽象类定义关键字 abstract class
  • 从成员上看
    • 接口成员固定形式,成员变量,成员方法
    • 抽象类可以有抽象方法,非抽象方法,成员变量
  • 使用上看
    • 接口需要实现类实现,支持多实现
    • 抽象类要子类继承,单继承
  • 设计思想
    • 抽象类,是这个继承体现中所有事务的共性内容
    • 接口,是这个继承体现中事务的部分额外功能

多态

多态 : 一个事务具备的不同形态,叫做多态

  • 实例 :

    • 你: 现在教室里面,你的形态是学习 (学生形态)

      出去逛商场,你的形态是顾客

      发现一个孩子落水,施救,英雄形态

    • 狗: 当宠物

      攻击外人, 看家的

      疯狗

对象的多态性

  • 对象多态性前提 :

    • 要有继承或者接口实现
    • 方法的重写
    • 父类或者接口的引用变量,指向自己的子类或者实现类对象 (定义)
  • 子类父类多态实现

    public class Person {
    	public void eat() {
    		System.out.println("人在吃饭");
    	}
    }
    public class Student extends Person{
    	public void eat() {
    		System.out.println("学生在吃饭");
    	}
    }
    
    public static void main(String[] args) {
        //实现子类继承父类的 多态程序
        //学生是一个人
        //父类或者接口的引用变量,指向自己的子类或者实现类对象
        /*
        * Person 父类类型
        * p 是父类类型的引用变量
        * new Student() 对象,是Person的子类对象
        */
        Person p = new Student();
        p.eat(); // 执行子类的方法重写
    }
    
  • 抽象类和子类

    public abstract class Animal {
    	public abstract void eat();
    }
    
    public class Cat extends Animal {
    	public void eat() {
    		System.out.println("猫吃猫粮");
    	}
    }
    
    public static void main(String[] args) {
    	//抽象类和子类的多态形式
    	//父类类型 变量名 = new 子类对象();
    	Animal a = new Cat();
    	a.eat();
    }
    
  • 接口和实现类

    public interface MyInterface {
    	public abstract void inter();
    }
    
    public class MyInterfaceImpl implements MyInterface{
    	public void inter() {
    		System.out.println("实现类重写方法");
    	}
    }
    
    public static void main(String[] args) {
        //接口和实现类的多态程序
    
        //接口类型  变量名 = new 实现类对象()
        MyInterface my = new MyInterfaceImpl();
        my.inter();
    }
    

多态的实现细节

  • 多态的程序中,子类父类中成员变量特点
    • 编译期 : 看父类中是否有这个变量,如果有编译成功,没有编译失败.
    • 运行期 : 运行的是父类中的成员变量
  • 多态的程序中,子类父类中成员方法特点
    • 编译期 : 看父类中是否有这个方法,如果有编译成功,没有编译失败.
    • 运行期 : 运行子类的方法重写
  • 小总结: Fu f = new Zi();
    • 成员变量 : 编译看左边,运行看左边
    • 成员方法 : 编译看左边,运行看右边

为什么编译是父类,运行是子类 (成员方法)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jP8GMiHH-1594817802098)(images/编译和运行的区别.jpg)]

多态转型

public static void main(String[] args) {
    /*
    * 多态创建对象
    * Cat和Dog都继承Animal
    * 调用子类父类的共性内容 eat()
    * 调用不了,子类的特有内容 catchMouse()  lookHome()
    */
    Animal a = new Cat();
    a.eat();

    //类型强制转换, 向下转型
    //已经提升为Animal类型的Cat对象,强制转换Cat类型
    Cat c = (Cat)a;
    //对象c 调用Cat类的特有成员,共有成员
    c.catchMouse();
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GDxIdDFQ-1594817802109)(images/类的转换.jpg)]

  • 多态的好处和弊端:
    • 好处 : 运行子类的重写方法,多态程序中可以随时扩展子类对象
    • 弊端 : 多态中,能调用子类父类的共有成员,不能调用子类的特有成员

类型转换时候出现的异常问题

类型转换异常 : ClassCastException

/*
 *  Animal a = new Cat();
 *  Animal抽象的类,可以有多个子类产生
 *  
 *  Animal a = new 任何子类();
 */
public class PolymorphismTest {
	public static void main(String[] args) {
		Animal a = new Dog();
		a.eat();
		
		Cat c = (Cat)a;
		c.catchMouse();
	}
}

Exception in thread "main" java.lang.ClassCastException: polymorphism06.Dog cannot be cast to polymorphism06.Cat
	at polymorphism06.PolymorphismTest.main(PolymorphismTest.java:13)

解决异常的出现 : 关键是在要转换的对象 a上, 判断出这个a这个引用,是Dog对象还是Cat对象.

  • 运算符 instanceof 做比较

    • 比较的结果是布尔类型

    • instanceof 比较出, a到底是哪个类的对象

    • 语法 :

      引用类型变量 instanceof 类名
      例子 : a instanceof Cat  含义 : a是不是Cat对象呢
      
      
    public static void main(String[] args) {
        Animal a = new Cat();
        a.eat();
    
        //判断a,如果是Cat对象,强制转换
        if(a instanceof Cat) {
            Cat c = (Cat)a; 
            c.catchMouse();
        }
    
        //判断a,如果是Dog对象,强制转换
        else if(a instanceof Dog) {
            Dog d = (Dog)a;
            d.lookHome();
        }
    }
    
    
    

    多态案例

    需求 : 有一台笔记本电脑,笔记本上面有接口存在 USB, USB是真实存在的接口,使用笔记本的人可以向接口上连接一些外接设备, 鼠标,键盘,手机,打印机 …

    笔记本的厂家,不会预先想到USB接口上,会连接哪些设备

​ 设计一台笔记本电脑,出现USB接口,可以连接任意的外接设备

核心的技术点 : 方法的参数是接口类型,调用方法传递实现类对象,多态调用,执行实现类的重写方法

/*
 * 接口USB : 就是一个规则
 * 规则的具体的体现 : 接口中的抽象方法
 */
public interface USB {
	//设备开机
	public abstract void open();
	
	//设备关键
	public abstract void close();
}


/*
 * 鼠标类 : 连接到USB接口,必须实现接口的规则
 */
public class Mouse implements USB{

	@Override
	public void open() {
		System.out.println("鼠标开机");
	}

	@Override
	public void close() {
		System.out.println("鼠标关机");
	}
}


/*
 * 键盘类 : 连接到USB接口,必须实现接口的规则
 */
public class Keyboard implements USB{

	@Override
	public void open() {
		System.out.println("键盘开机");
	}

	@Override
	public void close() {
		System.out.println("键盘关机");
	}

}

/*
 * 定义笔记本类
 */
public class Computer {
	/*
	 * 定义方法: 笔记本使用USB接口上的设备
	 * 方法的计算结果,返回值类
	 * 方法的参数,是未知的数据, USB接口上的外接设备 (鼠标,键盘)
	 * 方法的参数,不能写某一个设备(程序写死了)
	 * 但是 : 无论鼠标或者是键盘,还是其他设备... 必须满足USB接口规则!!
	 * 参数 : 写的是接口
	 * 
	 * USB u = new Mouse()
	 */
	public void useUSB(USB u) {
		//接口引用变量 u 调用方法
		u.open();
		u.close();
	}
}

public static void main(String[] args) {
    //创建笔记本的对象,调用笔记本的功能
    Computer computer = new Computer();
    /*
    * 调用笔记本的功能, 使用USB接口设备功能
    * 方法的参数是USB的接口类型
    * 接口没有对象, 能传递的参数只有接口实现类的对象
    */
    computer.useUSB( new Mouse() );
    computer.useUSB( new Keyboard()  );
}		

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DUbN624w-1594817802111)(images/方法的参数是接口.jpg)]

static 静态

static修饰符 : 成员修饰符,只能修饰类的成员 (变量和方法), 方法里面不能使用static修饰

被static修饰的成员,称为静态成员.

静态成员的内存图

/*
 *  定义一些人的属性和行为
 *    指定一个属性 : 国籍
 */
public class Person {
	String name;
	int age;
	static String country;
	
	public void eat() {
		System.out.println("人在吃饭");
	}
}


public static void main(String[] args) {
    //创建Person对象
    Person p1 = new Person();
    p1.name  = "张三";
    p1.age = 20;
    p1.country = "中国";

    Person p2 = new Person();
    p2.name = "李四";
    p2.age = 21;
    //p2.country = "中国";
    System.out.println(p2.country);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qTEvek9Z-1594817802113)(images/静态内存图.jpg)]

静态的调用规则

内存图进行分析,静态的成员在内存中有自己的所属,属于自己的类.

因此 : 静态的调用方式 : 类名.静态成员

System.out.println(Person.country);

Person.eat();

静态使用的注意事项

  • 不能在静态上下文中引用非静态变量
    • 静态不能直接使用非静态
    • 原因 : 生命周期,静态成员优先于非静态的成员出现在内存中
      • 先人(静态)不能调用后人(非静态)
  • 静态方法中,进制使用this和super
    • this 和 super都和对象有关联
    • 静态优先于对象存在

静态和对象无关性

多态 : 对象的多态性

静态成员 : 属于自己的类,和对象无关!!

public static void main(String[] args) {
    Fu f = new Zi();
    System.out.println(f.s); //s 静态变量,编译运行全是父类
    f.show(); // 方法show()静态方法,编译运行全那是父类
}

成员的调用方式

  • 静态成员
    • 类名调用
    • 可以被对象调用 X javac 编译器,直接编译为类名!
  • 非静态成员
    • 只能被对象调用

main方法解释

  • public : 被JVM调用,权限必须足够大
  • static : JVM通过类名调用方法main
  • void : 返回值,返回调用者, JVM获得返回值没有意义
  • main : 名字固定
  • String[] args : 存储字符串数组, 以后会添加JVM的启动参数

静态成员和非静态成员的区别

  • 内存上看区别
    • 静态成员变量,跟随类进入到静态区
    • 非静态成员变量,跟随对象进入到堆内存
  • 所属上看区别
    • 静态成员变量,属于自己的类
    • 非静态成员变量,属于对象
  • 从生命周期上看区别
    • 静态成员优先于非静态进入内存,在静态区里,程序结束才释放,最长
    • 非静态成员进入堆,对象成为垃圾后,JVM进行回收,相对较短
  • 调用方式上看
    • 静态类名调用
    • 非静态对象调用
  • 数据使用上看
    • 静态的成员,是所有对象的共享数据
    • 非静态的成员,是对象自己的特有数据

什么时候使用静态修饰

具体事务具体分析了,根据分析的结果,决定是否使用静态修饰

分析方法 : 分析这些事务之间是否存在着共享数据,出现共享数据,static修饰

以上说的是静态的成员变量

什么时候使用静态方法 : 如果方法中的功能使用了静态的成员变量,这个方法就应该static修饰

final修饰符

final翻译为最终的,不可改变的

  • 可以修饰类

    public final class A{} 最终类
    最终类不被子类继承, A类没有孩子 (太监类)
    以前学过最终类 : String,Scanner,System
    
    
  • 可以修饰方法

    public final 返回值类型 方法名(参数列表){} 最终方法
    最终方法,不能被子类重写
    有些类,定义的方法,一部分很完美,另一些方法不是很完善
    
    
  • 可以修饰局部变量

    final 数据类型 变量名 = 值 ; 最终变量
    被final修饰的变量,一次赋值,终身不变,可以看成是常量
    final修饰的是引用类型,引用类固定的是内存地址
    
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值