06 面向对象:多态&抽象类&接口&权限修饰符&内部类
Posted fly-book
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了06 面向对象:多态&抽象类&接口&权限修饰符&内部类相关的知识,希望对你有一定的参考价值。
多态:
/* 多态(polymorphic)概述 * 事物存在的多种形态 多态前提 * a:要有继承关系。 * b:要有方法重写。 * c:要有父类引用指向子类对象。 * 成员变量 * 编译看左边(父类),运行看左边(父类)。 * 成员方法 * 编译看左边(父类),运行看右边(子类)。动态绑定 * 静态方法 * 编译看左边(父类),运行看左边(父类)。 * (静态和类相关,算不上重写,所以,访问还是左边的) * 只有非静态的成员方法,编译看左边,运行看右边 */ class Demo_Polymorphic { public static void main(String[] args) { Animal a = new Cat(); // 父类引用指向子类对象 a.eat(); // 猫吃鱼 // 如果父类没有eat方法就会报错,编译看左边(父类) System.out.println(a.num); // 10 成员变量,运行看父类 a.method(); // Animal static method ,相当于Animal.method() } } class Animal { int num = 10; public void eat(){ System.out.println("动物吃饭"); } public static void method(){ System.out.println("Animal static method"); } } class Cat extends Animal { int num = 20; public void eat(){ System.out.println("猫吃鱼"); } public static void method(){ System.out.println("Cat static method"); } }
/* * A:多态的好处 * a:提高了代码的维护性(继承保证) * b:提高了代码的扩展性(由多态保证) * B:可以当作形式参数,可以接收任意子类对象 * C:多态的弊端 * 不能使用子类的特有属性和行为。 */ class Demo_Polymorphic1 { public static void main(String[] args) { Animal a = new Cat();// 向上转型 a.eat(); Cat c = (Cat)a; //向下转型 c.method(); // Animal a2 = new Dog(); methods(new Dog()); } public static void methods(Animal a){ // 作形式参数 if (a instanceof Cat) { Cat c = (Cat)a; c.method(); } else if (a instanceof Dog) { Dog d = (Dog)a; d.method(); }else{ a.eat(); } } } class Animal { public void eat(){ System.out.println("动物吃饭"); } } class Cat extends Animal { public void eat(){ System.out.println("猫吃鱼"); } public void method(){ System.out.println("猫捉老鼠"); } } class Dog extends Animal { public void eat(){ System.out.println("狗吃肉"); } public void method(){ System.out.println("狗看门"); } }
抽象的特点:
/* 抽象类特点 * a:抽象类和抽象方法必须用abstract关键字修饰 * abstract class 类名 {} * public abstract void eat(); * b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口 * c:抽象类不能实例化那么,抽象类如何实例化呢? * 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。 * d:抽象类的子类 * 要么是抽象类 * 要么重写抽象类中的所有抽象方法 * * 抽象类特点B:抽象类特点 * a:抽象类和抽象方法必须用abstract关键字修饰 * abstract class 类名 {} * public abstract void eat(); * b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口 * c:抽象类不能实例化那么,抽象类如何实例化呢? * 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。 * d:抽象类的子类 * 要么是抽象类 * 要么重写抽象类中的所有抽象方法 */ class Demo_Abstract { public static void main(String[] args) { // Animal a = new Animal();//错误: Animal是抽象的; 无法实例化 new Cat().method(); } } abstract class Animal { public abstract void method(); public void eat(){ System.out.println("eat"); } } class Cat extends Animal { public void method(){ System.out.println("捉老鼠"); } }
抽象类的成员特点:
* 抽象类的成员特点
* a:成员变量:既可以是变量,也可以是常量。abstract是否可以修饰成员变量?不能修饰成员
变量
* b:构造方法:有。
* 用于子类访问父类数据的初始化。
* c:成员方法:既可以是抽象的,也可以是非抽象的。
* 抽象类的成员方法特性:
* a:抽象方法 强制要求子类做的事情。
* b:非抽象方法 子类继承的事情,提高代码复用性。
一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
* 可以
* 这么做目的只有一个,就是不让其他类创建本类对象,交给子类完成
abstract不能和哪些关键字共存
abstract和static
被abstract修饰的方法没有方法体
被static修饰的可以用类名.调用,但是类名.调用抽象方法是没有意义的
abstract和final
被abstract修饰的方法强制子类重写
被final修饰的不让子类重写,所以他俩是矛盾
abstract和private
被abstract修饰的是为了让子类看到并强制重写
被private修饰不让子类访问,所以他俩是矛盾的
abstract class Demo { //public static abstract void print(); //错误: 非法的修饰符组合: abstract 和static //public final abstract void print(); //错误: 非法的修饰符组合: abstract 和final private abstract void print(); //错误: 非法的修饰符组合: abstract和private }
接口:
/* * A:接口概述 * 从狭义的角度讲就是指java中的interface * 从广义的角度讲对外提供规则的都是接口 * B:接口特点 * a:接口用关键字interface表示 * interface 接口名 {} * b:类实现接口用implements表示 * class 类名 implements 接口名 {} * c:接口不能实例化 * 按照多态的方式来实例化。 * d:接口的子类 * a:可以是抽象类。但是意义不大。 * b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案) */ class Demo_Interface { public static void main(String[] args) { // Inter i = new Inter();//错误: Inter是抽象的; 无法实例化 Inter i = new A(); // 按照多态的方式实例化 i.print(); new Y().print(); } } interface Inter { public abstract void print(); // 接口中的方法都是抽象的 } class A implements Inter { public void print(){ System.out.println("a"); } } /* 接口成员特点 * 成员变量;只能是常量,并且是静态的并公共的。 * 默认修饰符:public static final * 建议:自己手动给出。 * 构造方法:接口没有构造方法。 * 成员方法:只能是抽象方法。 * 默认修饰符:public abstract * 建议:自己手动给出。 */ interface X { public static final int num = 10; public abstract void print(); // public X(){}//接口没有构造方法 // public void print(){} // 只能是抽象方法 } class Y implements X { public Y(){ super(); // 父类object } public void print(){ System.out.println(num); } } class Demo3_Interface { public static void main(String[] args) { System.out.println("Hello World!"); } } /* * 类与类,类与接口,接口与接口的关系 * a:类与类: * 继承关系,只能单继承,可以多层继承。 * b:类与接口: * 实现关系,可以单实现,也可以多实现。 * 并且还可以在继承一个类的同时实现多个接口。 * c:接口与接口: * 继承关系,可以单继承,也可以多继承。 */ interface InterA { public abstract void printA(); } interface InterB { public abstract void printB(); } interface InterC extends InterB,InterA { } //class Demo implements InterA,implements InterB { //这么做不允许是非法的 class Demo extends Object implements InterA,InterB { public void printA() { System.out.println("printA"); } public void printB() { System.out.println("printB"); } }
class Demo3_Interface { public static void main(String[] args) { System.out.println("Hello World!"); } } /* * A:类与类,类与接口,接口与接口的关系 * a:类与类: * 继承关系,只能单继承,可以多层继承。 * b:类与接口: * 实现关系,可以单实现,也可以多实现。 * 并且还可以在继承一个类的同时实现多个接口。 * c:接口与接口: * 继承关系,可以单继承,也可以多继承。 */ interface InterA { public abstract void printA(); } interface InterB { public abstract void printB(); } interface InterC extends InterB,InterA { } //class Demo implements InterA,implements InterB { //这么做不允许是非法的 class Demo extends Object implements InterA,InterB { public void printA() { System.out.println("printA"); } public void printB() { System.out.println("printB"); } } class Demo3_Interface { public static void main(String[] args) { System.out.println("Hello World!"); } } /* * A:类与类,类与接口,接口与接口的关系 * a:类与类: * 继承关系,只能单继承,可以多层继承。 * b:类与接口: * 实现关系,可以单实现,也可以多实现。 * 并且还可以在继承一个类的同时实现多个接口。 * c:接口与接口: * 继承关系,可以单继承,也可以多继承。 */ interface InterA { public abstract void printA(); } interface InterB { public abstract void printB(); } interface InterC extends InterB,InterA { } //class Demo implements InterA,implements InterB { //这么做不允许是非法的 class Demo extends Object implements InterA,InterB { public void printA() { System.out.println("printA"); } public void printB() { System.out.println("printB"); } } class Demo3_Interface { public static void main(String[] args) { System.out.println("Hello World!"); } } /* * A:类与类,类与接口,接口与接口的关系 * a:类与类: * 继承关系,只能单继承,可以多层继承。 * b:类与接口: * 实现关系,可以单实现,也可以多实现。 * 并且还可以在继承一个类的同时实现多个接口。 * c:接口与接口: * 继承关系,可以单继承,也可以多继承。 */ interface InterA { public abstract void printA(); } interface InterB { public abstract void printB(); } interface InterC extends InterB,InterA { } //class Demo implements InterA,implements InterB { //这么做不允许是非法的 class Demo extends Object implements InterA,InterB { public void printA() { System.out.println("printA"); } public void printB() { System.out.println("printB"); } }
抽象类和接口的区别
* 成员区别 * 抽象类: * 成员变量:可以变量,也可以常量 * 构造方法:有 * 成员方法:可以抽象,也可以非抽象 * 接口: * 成员变量:只可以常量 * 成员方法:只可以抽象 * 关系区别 * 类与类 * 继承,单继承 * 类与接口 * 实现,单实现,多实现 * 接口与接口 * 继承,单继承,多继承 * 设计理念区别 * 抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。 * 接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。
为什么要有包:
* 将字节码(.class)进行分类存放
* 包其实就是文件夹
包的定义及注意事项
* A:定义包的格式
* package 包名;
* 多级包用.分开即可
* B:定义包的注意事项
* A:package语句必须是程序的第一条可执行的代码
* B:package语句在一个java文件中只能有一个
* C:如果没有package,默认表示无包名
如何编译运行带包的类:
* a:javac编译的时候带上-d即可
* javac -d . HelloWorld.java
* b:通过java命令执行。
* java 包名.HellWord
import关键字的概述和使用:
* 为什么要有import
* 其实就是让有包的类对调用者可见,不用写全类名了
* 导包格式
* import 包名;
* 注意:
这种方式导入是到类的名称。
虽然可以最后写*,但是不建议。
四种权限修饰符:
本类 | 同一个包下(子类和无关类) | 不同包下(子类) | 不同包下(无关类) | |
private | Y | |||
默认 | Y | Y | ||
protected | Y | Y | Y | |
public | Y | Y | Y | Y |
类及其组成所使用的常见修饰符:
* A:修饰符: * 权限修饰符:private,默认的,protected,public * 状态修饰符:static,final * 抽象修饰符:abstract * B:类: * 权限修饰符:默认修饰符,public * 状态修饰符:final * 抽象修饰符:abstract * 用的最多的就是:public * C:成员变量: * 权限修饰符:private,默认的,protected,public * 状态修饰符:static,final * 用的最多的就是:private * D:构造方法: * 权限修饰符:private,默认的,protected,public * 用的最多的就是:public * E:成员方法: * 权限修饰符:private,默认的,protected,public * 状态修饰符:static,final * 抽象修饰符:abstract * 用的最多的就是:public * F:除此以外的组合规则: * 成员变量:public static final 接口 * 成员方法: * public static * public abstract * public final
内部类访问特点 * a:内部类可以直接访问外部类的成员,包括私有。 * b:外部类要访问内部类的成员,必须创建对象。 * 外部类名.内部类名 对象名 = 外部类对象.内部类对象; class Demo_Inner { public static void main(String[] args) { Outer.Inner oi = new Outer().new Inner(); oi.method(); // 访问内部类的私有使用 Outer2 o = new Outer2(); o.print(); // 访问静态成员内部类 Outer3.Inner o3 = new Outer3.Inner(); o3.method(); Outer4.Inner.method(); } } class Outer { private int num = 10; class Inner { public void method(){ System.out.println(num); } } } // 内部类的私有使用 class Outer2 { private int num = 10; private class Inner { public void method(){ System.out.println(num); } } public void print(){ new Inner().method(); } } /* 静态成员内部类 * 成员内部类被静态修饰后的访问方式是: * 外部类名.内部类名 对象名 = 外部类名.内部类对象; */ class Outer3 { static class Inner { public void method(){ System.out.println("static"); } } } class Outer4 { static class Inner { public static void method(){ System.out.println("static"); } } }
使用已知的变量,在控制台输出30,20,10。
// 内部类之所以能获得外部类的成员,是因为他能获取到外部类的引用 外部类名.this class Outer { public int num = 10; class Inner { public int num = 20; public void show() { int num = 30; System.out.println(num); System.out.println(this.num); System.out.println(Outer.this.num); } } } class InnerClassTest { public static void main(String[] args) { Outer.Inner oi = new Outer().new Inner(); oi.show(); } } class Demo_InnerClass { public static void main(String[] args) { Outer o = new Outer(); o.method(); } } // 局部内部类 class Outer { public void method(){ final int num = 10; // 局部内部类访问局部变量必须用final修饰 class Inner { public void print(){ System.out.println(num); } } new Inner().print(); } /* public void Test(){ new Inner().print();// 错误,局部内部类,只能在其所在的方法中访问 } */ } /* * 局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么? 因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周 期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部 变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可 以继续使用 但是jdk1.8,如果在书写代码时候,没有手动添加,系统底层也会默给你final */
匿名内部类:
/* * A:匿名内部类 * 就是内部类的简化写法。 * B:前提:存在一个类或者接口 * 这里的类可以是具体类也可以是抽象类。 * C:格式: new 类名或者接口名(){ 重写方法; } * D:本质是什么呢? * 是一个继承了该类或者实现了该接口的子类匿名对象。 */ class Demo_InnerClass2 { public static void main(String[] args) { new Outer().method(); } } interface Inner { public abstract void print(); } class Outer { public void method(){ new Inner(){ public void print(){ System.out.println("Hello World!"); } }.print(); } } // 匿名内部类重写多个方法调用 // 建议匿名类只针对重写一个方法时候使用 interface Inner2 { public abstract void print1(); public abstract void print2(); } class Outer2 { public void method(){ Inner2 i = new Inner2(){ // 父类引用指向子类对象 public void print1(){ System.out.println("print1"); } public void print2(){ System.out.println("print1"); } /* public void print3(){ System.out.println("print3"); } */ }; i.print1(); i.print2(); // i.print3(); // 匿名内部类是不能向下转型的,因为没有自类类名 } }
class Test_NoNameInnerClass { public static void main(String[] args) { Outer.method().show(); // 相当于 Inter i = Outer.method(); i.show(); } } interface Inter { void show(); } class Outer { public static Inter method(){ return new Inter(){ public void show(){ System.out.println("Hello World!"); } }; } } /* Hello World! */
重写补充:返回值类型是子父类
/* 重写:子父类出现了一模一样的方法 (注意:返回值类型可以是子父类) */ class Demo_FaSonClass { public static void main(String[] args) { } } class Person { public void print(){ System.out.println("Hello World!"); } } class Person2 extends Person { public void print(){ System.out.println("Hello World!2"); } } class Father { public Person method(){ return new Person(); //Person与Person2 是子父类 } } class Son extends Father { public Person2 method(){ return new Person2(); //Person与Person2 是子父类 } }
以上是关于06 面向对象:多态&抽象类&接口&权限修饰符&内部类的主要内容,如果未能解决你的问题,请参考以下文章