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 是子父类
}
}
上一篇:基于物理规则的渲染(PBR)


下一篇:MySQL踩坑及MySQL解压版安装