1. 多态
-
多态polymorhic概述
- 事物存在的多种形态。
- 多态前提
- 要有继承关系
- 要有方法重写
- 要有父类引用指向子类对象
- 案例演示
- 代码体现多态
-
class Demo1_Polymorphic{ public static void main(String[] args) { Cat c = new Cat(); c.eat(); Animal a = new Cat(); // 父类引用指向子类对象 a.eat(); // 输出“猫吃鱼” } } class Animal { public void eat() { System.out.println("动物吃饭"); } } class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } }
- 多态中的成员访问特点
- 成员变量
- 编译看左边(父类),运行看左边(父类)
- Father f = new Son();
-
class Demo2_Polymorphic { public static void main(String[] args) { Father f = new Son(); System.out.println(f.num); //输出10 } } class Father { int num = 10; } class Son extends Father { int num = 20; }
如果再上面例子的基础上,再生成一个Son类对象,则
-
class Demo2_Polymorphic { public static void main(String[] args) { Father f = new Son(); System.out.println(f.num); //输出10 Son s = new Son(); System.out.println(s.num); //输出20 } } class Father { int num = 10; } class Son extends Father { int num = 20; }
- 成员方法
- 编译看左边(父类),运行看右边(子类)——又称“动态绑定”
- Father f = new Son();
- 编译时,看父类中有没有该成员方法,有则编译成功;运行则动态绑定到子类的成员方法上,运行子类的成员方法。
-
class Demo3_Polymorphic { public static void main(String[] args) { Father f = new Son(); f.print();// 输出son } } class Father { int num = 10; public void print() { System.out.println("father"); } } class Son extends Father { int num = 20; public void print() { System.out.println("son"); } }
- 静态方法
- 编译看左边(父类),运行看左边(父类)
- 静态和类相关,算不上重写,所以,访问还是左边的
-
class Demo4_Polymorphic { public static void main(String[] args) { Father f = new Son(); f.method(); //输出"father static method"; // 相当于是Father.method(); 调用父类的方法 } } class Father { int num = 10; public void print() { System.out.println("father"); } public static void method(){ System.out.println("father static method"); } } class Son extends Father { int num = 20; public void print() { System.out.println("son"); } public static void method(){ System.out.println("son static method"); } }
- 总结:
- 只有非静态的成员方法,编译看左边(父类),运行看右边(子类)
- 其他都是编译看左边(父类),运行看左边(父类)
- 成员变量
- 案例:超人的故事
- 通过该案例帮助理解多态的现象。
-
class Demo5_Polymorphic { public static void main(String[] args) { Person p = new SuperMan(); // 父类引用指向子类对象,超人提升为人 System.out.println(p.name);// 输出“John” p.谈生意(); // 输出"谈几个亿的大单子" //p.fly(); //编译出错 } } class Person { String name = "John"; public void 谈生意() { System.out.println("谈生意"); } } class SuperMan extends Person { String name = "Super man"; public void 谈生意() { System.out.println("谈几个亿的大单子"); } public void fly() { System.out.println("飞出去救人"); } }
超人作为人类身份的属性信息对外展示,Person类和SuperMan类中重写的方法,实际执行的是超人身份的方法;
在这个例子中,父类中没有fly方法,故编译失败,也无法执行。针对这个,要考虑下面的 向上转型和向下转型 的问题。
- 多态中 向上转型和向下转型
- 向上转型
- Person p = new SuperMan();
- 父类引用指向子类对象,就是向上转型
- 向下转型
- SuperMan sm = (SuperMan)p;
-
class Demo5_Polymorphic { public static void main(String[] args) { Person p = new SuperMan(); // 父类引用指向子类对象,超人提升为人 System.out.println(p.name);// 输出“John” p.谈生意(); // 输出"谈几个亿的大单子" //p.fly(); //编译出错 SuperMan sm = (SuperMan)p; // 向下转型 sm.fly(); } } class Person { String name = "John"; public void 谈生意() { System.out.println("谈生意"); } } class SuperMan extends Person { String name = "Super man"; public void 谈生意() { System.out.println("谈几个亿的大单子"); } public void fly() { System.out.println("飞出去救人"); } }
- 向上转型
-
补充参考:基本数据类型:
- 自动类型提升
- 强制类型转换
-
class Demo1_Polymorphic{ public static void main(String[] args) { int i = 10; byte b = 20; i = b; // 自动类型转换 b = (byte)i; // 强制类型转换 } }
- 多态的好处和弊端
- 多态的好处
- 提高了代码的维护性(继承保证)
- 提高了代码的扩展性(由多态保证)
- 可以当做形式参数
- 可以接收任意子类对象
- 多态的弊端
- 不能使用子类的特有属性和行为
- 案例演示
- method(Animal a) 方便Animal的所有子类的 重写的方法调用
- method(Cat c) 这种直接调用子类,出现并行子类,调用父类方法,需要些新的method方法,传入不同的类作为实参。
-
class Demo6_Polymorphic { public static void main(String[] args) { method(new Cat()); method(new Dog()); /* Animal a = new Cat(); Animal a = new Dog(); 开发的时候很少在创建对象的时候用父类引用指向子类对象, 直接创建子类对象更方便,可以使用子类中的特有属性和方法 */ } /* public static void method(Cat c) { c.eat(); } public static void method(Dog d) { d.eat(); }*/ public static void method(Animal a) { // 当做参数的时候,用多态最好,扩展性强 //关键字 instanceof 判断前边的引用是否是后边的数据类型 if (a instanceof Cat) { Cat c = (Cat)a; c.eat(); c.catchMouse(); }else if (a instanceof Dog) { Dog d = (Dog)a; d.eat(); d.lookHome(); }else { a.eat(); } /* // 如果把Dog强转成Cat,就会出现类型转换异常,ClassCastException Cat c = (Cat)a; c.eat(); c.catchMouse();*/ } } class Animal { public void eat() { System.out.println("动物吃饭"); } } class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } public void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal { public void eat() { System.out.println("狗吃肉"); } public void lookHome() { System.out.println("看家"); } }
- 多态的好处
2. 抽象类
- 抽象类概述
- 抽象就是看不懂的
- 抽象类的特点
- 抽象类和抽象方法必须用abstract关键字修饰
- abstract class 类名 ()
- public abstract void eat();
- 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者接口
- 抽象类不能实例化,那么,抽象类如何实例化呢?
- 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
- 抽象类的子类
- 要么是抽象类
- 要么重写抽象类中的所有抽象方法
- 案例演示
-
class Demo1_Abstract { public static void main(String[] args) { Animal a = new Cat(); a.eat(); print(a); } public static void print(Animal a) { a.eat(); } } abstract class Animal { // 抽象类 public abstract void eat(); // 抽象方法 } class Cat extends Animal { public void eat() { System.out.println("猫吃鱼"); } }
-
class Demo1_Abstract { public static void main(String[] args) { } public static void print(Animal a) { a.eat(); } } abstract class Animal { // 抽象类 public abstract void eat(); // 抽象方法 } class Cat extends Animal { //错误: Cat不是抽象的, 并且未覆盖Animal中的抽象方法eat() }
-
- 抽象类联系(猫狗,抽象类为动物)
-
具体事物:猫,狗
共性:姓名,年龄,吃饭
猫的特性:抓老鼠
狗的特性:看家 -
class Test1_Animal { public static void main(String[] args) { Cat c = new Cat("加菲",8); System.out.println(c.getName() + "..." + c.getAge()); c.eat(); c.catchMouse(); Dog d = new Dog("八公",30); System.out.println(d.getName() + "..." + d.getAge()); d.eat(); d.lookHome(); } } /* 案例演示: 具体事物:猫,狗 共性:姓名,年龄,吃饭 猫的特性:抓老鼠 狗的特性:看家 */ abstract class Animal { private String name; private int age; public Animal(){} public Animal(String name,int age) { this.name = name; this.age = age; } public void setName(String name) { // 设置姓名 this.name = name; } public String getName() { // 获取姓名 return name; } public void setAge(int age) { // 设置年龄 this.age = age; } public int getAge() { // 获取年龄 return age; } public abstract void eat(); // 抽象方法:吃饭 } class Cat extends Animal { public Cat(){} public Cat(String name,int age) { super(name,age); } public void eat() { System.out.println("猫吃鱼"); } public void catchMouse() { System.out.println("抓老鼠"); } } class Dog extends Animal { public Dog(){} public Dog(String name,int age) { super(name,age); } public void eat() { System.out.println("狗吃肉"); } public void lookHome() { System.out.println("抓老鼠"); } }
-
class Test2_Teacher { public static void main(String[] args) { Teacher t = new BaseTeacher(); print(t); print(new EmpTeacher()); } public static void print(Teacher t) { t.teach(); } } /* 具体事物:基础班老师,就业班老师 共性:姓名、年龄、讲课 */ abstract class Teacher { private String name; private int age; public abstract void teach(); public Teacher() {} public Teacher(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } } class BaseTeacher extends Teacher { public BaseTeacher() {} public BaseTeacher(String name, int age) { super(name, age); } public void teach() { System.out.println("基础班老师 讲课"); } } class EmpTeacher extends Teacher { public EmpTeacher() {} public EmpTeacher(String name, int age) { super(name, age); } public void teach() { System.out.println("就业班老师 讲课"); } }
-
class Test3_Student { public static void main(String[] args) { state(new BaseStudent()); state(new EmpStudent()); } public static void state(Student s) { s.study(); } } /* 具体事物:基础班学生,就业班学生 共性:姓名,年龄,学习 */ abstract class Student { private String name; private int age; public abstract void study(); public Student() {} public Student(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getNamge() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } } class BaseStudent extends Student { public BaseStudent() {} public BaseStudent(String name, int age) { super(name,age); } public void study() { System.out.println("基础班学生在学习"); } } class EmpStudent extends Student { public EmpStudent() {} public EmpStudent(String name, int age) { super(name,age); } public void study() { System.out.println("就业班学生在学习"); } }
-
class Test4_Employee { public static void main(String[] args) { Coder c = new Coder("John", "001", 10000.00); c.work(); Manager m = new Manager("Ann", "033", 40000.00, 10000); m.work(); } } /* 假如我们在开发一个系统时,需要对程序员类进行设计。 程序员包含3个属性: 姓名 工号 工资 经理:出了含有程序员的属性外,还有一个奖金属性 用继承的思想设计出程序员类和经理类。 要求类中提供必要的方法进行属性访问。 */ abstract class Employee { private String name; private String code; private double salary; public Employee() {} public Employee(String name, String code, double salary) { this.name = name; this.code = code; this.salary = salary; } public void setName(String name) { this.name = name; } public String getName(){ return name; } public void setCode(String code) { this.code = code; } public String getCode(){ return code; } public void setSalary(double salary) { this.salary = salary; } public double getSalary(){ return salary; } public abstract void work(); } class Manager extends Employee { private int bonus; public Manager() {} public Manager(String name, String code, double salary, int bonus) { super(name,code,salary); this.bonus = bonus; } public void setBonus(int bonus) { this.bonus = bonus; } public int getBonus(){ return bonus; } public void work() { System.out.println("项目经理" + this.getName() + "在工作"); System.out.println("奖金是" + this.getBonus()); } } class Coder extends Employee { public Coder() {} public Coder(String name, String code, double salary) { super(name,code,salary); } public void work() { System.out.println("程序员" + this.getName() + "在工作"); } }
-
- 抽象类和抽象方法必须用abstract关键字修饰
- 抽象类的注意问题
- 一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
- 可以。
目的只有一个,就是不让其他类创建本类对象,交给子类完成
- 可以。
-
abstract不能和哪些关键字共存?
-
abstract 和 static
被abstract修饰的方法没有方法体;
被static修饰的可以用 类名.调用,但是类名.调用 抽象方法是没有意义的。 -
abstract 和 final
被abstract修饰的方法强制子类重写;
被final修饰的方法,不让子类重写。这两个修饰词是矛盾的。 -
abstract 和 private
被abstract修饰的是为了让子类看到并强制重写
被private修饰的不让子类访问,所以他两是矛盾的。 -
class Demo4_Abstract { public static void main(String[] args) { System.out.println("Hello World!"); } } /* 面试题1: 一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义? 答: 可以。 目的只有一个,就是不让其他类创建本类对象,交给子类完成 面试题2: abstract不能和哪些关键字共存? 答: abstract 和 static 被abstract修饰的方法没有方法体; 被static修饰的可以用 类名.调用,但是类名.调用 抽象方法是没有意义的。 abstract 和 final 被abstract修饰的方法强制子类重写; 被final修饰的方法,不让子类重写。这两个修饰词是矛盾的。 abstract 和 private 被abstract修饰的是为了让子类看到并强制重写 被private修饰的不让子类访问,所以他两是矛盾的。 */ abstract class Demo { // public static abstract void print(); // Demo4_Abstract.java:21: 错误: 非法的修饰符组合: abstract和static // public final abstract void print(); // Demo4_Abstract.java:29: 错误: 非法的修饰符组合: abstract和final // private abstract void print(); // Demo4_Abstract.java:36: 错误: 非法的修饰符组合: abstract和private }
-
- 一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
3. 接口
- 接口概述
- 从狭义的角度讲,就是指java中的interface
- 从广义的角度讲,就是对外提供规则的都是接口
- 接口特点
- 接口关键字interface表示
- interface 接口名 {}
- 类实现接口用 implements表示
- class 类名 implements 接口名 {}
- 接口不能实例化
- 那么,接口如何实例化呢?
- 按照多态的方式来实例化
- 接口的子类
- 可以是抽象类,但是意义不大。
- 可以使具体类,要重写接口中的所有抽象方法(推荐方案)
- 接口关键字interface表示
- 案例演示:接口特点
-
class Demo1_Interface { public static void main(String[] args) { //Inter i = new Inter(); // 接口不能被实例化,因为调用抽象方法没有意义 Inter i = new Demo(); i.print(); } } interface Inter { public abstract void print(); // 接口中的方法都是抽象的 } class Demo implements Inter { public void print() { System.out.println("print"); } }
-
class Demo1_Interface { public static void main(String[] args) { } } interface Inter { public abstract void print(); // 接口中的方法都是抽象的 } abstract class Demo implements Inter { }
-
-
接口的成员特点:
-
成员变量
- 只能是常量,并且是静态的,并公共的。
- 默认修饰符:public static final(即使不手写,也会默认添加)
- 建议:自己手动给出
-
构造方法
- 接口没有构造方法
-
成员方法
- 只能是抽象方法
- 默认修饰符:public abstract
- 建议:自己手动给出
- 只能是抽象方法
- 案例演示
-
class Demo1_Interface { public static void main(String[] args) { Demo d = new Demo(); d.print(); System.out.println(Inter.num); } } interface Inter { public static final int num = 10; // 系统会默认添加public static final,建议手动写出 // 这三个关键词没有顺序区别 // public Inter(){} 报错,接口中没有构造方法 // public void print() {} // 接口中不能定义非抽象方法 void print(); // 前面默认添加了public abstract修饰词 public abstract void print2(); } class Demo /* extends Object */ implements Inter { // 一个类不写继承任何一个类,默认继承Object类 public void print() { System.out.println(num); } public void print2() {} }
-
class Test1_Aniaml { public static void main(String[] args) { Cat c = new Cat("加菲",8); c.eat(); c.sleep(); JumpCat jc = new JumpCat("跳高猫",3); jc.eat(); jc.sleep(); jc.jump(); } } /* 动物类:姓名,年龄,吃饭,睡觉 猫和狗 动物培训接口:跳高 */ abstract class Animal { private String name; private int age; public Animal(){} public Animal(String name,int age){ this.name = name; this.age = age; } public void setName(String name){ this.name = name; } public String getName(){ return name; } public void setAge(int age){ this.age = age; } public int getAge(){ return age; } public abstract void eat(); public abstract void sleep(); } interface Jumping { public void jump(); } class Cat extends Animal { public Cat(){} public Cat(String name,int age){ super(name,age); } public void eat() { System.out.println("猫吃鱼"); } public void sleep() { System.out.println("侧着睡"); } } class JumpCat extends Cat implements Jumping { public JumpCat(){} public JumpCat(String name,int age){ super(name,age); } public void jump() { System.out.println("猫跳高"); } }
-
-
3. 各种类,接口之间的关系
3.1 类与类,类与接口,接口与接口的关系
- 类与类
- 继承关系
- 只能单继承,可以多层继承
- 继承关系
- 类与接口
- 实现关系,可以单实现,也可以多实现
- 并且还可以在继承一个类的同时实现多个接口
-
class Demo1_Interface { public static void main(String[] args) { } } interface InterA { public abstract void printA(); } interface InterB { public abstract void printB(); } class Demo implements InterA,InterB { public void printA() { System.out.println("printA"); } public void printB() { System.out.println("printB"); } }
- 接口与接口
- 继承关系
- 可以单继承,也可以多继承。
-
class Demo1_Interface { public static void main(String[] args) { } } interface InterA { public abstract void printA(); } interface InterB { public abstract void printB(); } interface InterC extends InterA,InterB { }
- 继承关系
3.2 抽象类和接口的区别
- 成员区别
- 抽象类
- 成员变量:可以变量,也可以常量
- 构造方法:有
- 成员方法:可以抽象,也可以非抽象
- 接口
- 成员变量:只可以常量
- 成员方法:只可以抽象
- 抽象类
- 关系区别
- 类与类
- 继承,单继承
- 类与接口
- 实现,单实现,多实现
- 接口与接口
- 继承,单继承,多继承
- 类与类
- 设计理念区别
- 抽象类
- 被继承体现的是“is a”的关系。
- 抽象类中定义的是该继承体系的共性功能
- 接口
- 被实现体现的是“like a”的关系。
- 接口中定义的是该继承体系的扩展功能
4. 包package
- 为什么要有包
- 将字节码(.class)进行分类存放
- 包其实就是文件夹
- 包的概述
- 老师:增加、删除、修改、查询
- 方案1:按照功能分
- com.heima.add
- AddStudent
- AddTeacher
- com.heima.delete
- DeleteStudent
- DeleteTeacher
- com.heima.update
- UpdateStudent
- UpdateTeacher
- com.heima.find
- FindStudent
- FindTeacher
- com.heima.add
- 方案2:按照模块分
- com.heima.teacher
- AddTeacher
- DeleteTeacher
- UpdateTeacher
- FindTeacher
- com.heima.student
- AddStudent
- DeleteStudent
- UpdateStudent
- FindStudent
- com.heima.teacher
- 包的定义
- 格式
- package 包名;
- 多级包用“.” 分开即可
- 注意事项
- package语句必须是程序的第一条可执行的代码
- package语句在一个java文件中只能有一个
- 如果没有package,默认表示无包名
- 案例演示
-
package com.heima; // package语句必须是程序的第一条可执行的代码 // 一个文件内只能有一个package语句 class Demo1_Package { public static void main(String[] args) { } }
-
- 格式
- 如何编译运行带包的类
- 案例演示
- javac编译时加上-d即可
- javac -d . HelloWorld.java
- 通过java命令执行
- java 包名.HelloWorld
- java com.heima.Demo1_Package
- javac编译时加上-d即可
- 案例演示
- 不同包下类之间的访问
- 案例演示
-
package com.heima; // package语句必须是程序的第一条可执行的代码 // 一个文件内只能有一个package语句 import com.baidu.Person; import com.xxx.Student; //import java.util.Scanner; //在开发中我们用的都是导入具体的类 import java.util.*; //*代表通配符,他会到该包下挨个匹配,匹配上就导入 class Demo1_Package { public static void main(String[] args) { Person p = new Person("张三",23); System.out.println(p.getName() + "..." + p.getAge()); //p.print(); //在不同包下的无关类,不允许访问,因为是protected修饰的 /*Scanner sc = new Scanner(System.in); int x = sc.nextInt(); System.out.println(x);*/ Student s = new Student("李四",24); System.out.println(s.getName() + "..." + s.getAge()); s.method(); } }
-
import关键字的概述和使用
-
-
-
-
import 包名;
-
注意:
-
这种方式导入是到类的名称。
-
-
-
- package,import,class有没有顺序关系
- 有。
- package 第一行,只能一个文件一句
- import 中间,可以有多句
- class 放在这两个下面
-
5. 修饰符
- 四种权限修饰符
- private 本类;
- 默认 本类;同一个包下(子类和无关类)
- protected 本类;同一个包下(子类和无关类);不同包下(子类)
- public 本类;同一个包下(子类和无关类);不同包下(子类);不同包下(无关类)
- 修饰符
- 权限修饰符:private,默认的,protected,public
- 状态修饰符:static,final
- 抽象修饰符:abstract
- 类
- 权限修饰符:默认修饰符,public
- 状态修饰符:final
- 用的最多的就是:public
-
成员变量:
-
权限修饰符:private,默认的,protected,public
-
状态修饰符:static,final
-
用的最多的就是:private
-
-
构造方法:
-
权限修饰符:private,默认的,protected,public
-
用的最多的就是:public
-
-
成员方法:
-
权限修饰符:private,默认的,protected,public
-
状态修饰符:static,final
-
抽象修饰符:abstract
-
用的最多的就是:public
-
-
除此以外的组合规则:
-
成员变量:public static final
-
成员方法:
-
public static
-
public abstract
-
-
-
6. 内部类
-
-
内部类访问特点
-
内部类可以直接访问外部类的成员,包括私有。
-
外部类要访问内部类的成员,必须创建对象。
-
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
-
-
案例演示
-
class Demo1_InnerClass { public static void main(String[] args) { //Inner i = new Inner(); //i.method(); //外部类名.内部类名 = 外部类对象.内部类对象 Outer.Inner oi = new Outer().new Inner(); //创建内部类对象 oi.method(); } } class Outer { // 外部类 private int num = 10; class Inner { // 内部类 public void method() { System.out.println(num); } } }
-
class Demo2_InnerClass { public static void main(String[] args) { //Outer.Inner oi = new Outer().new Inner(); //内部类私有,无法调用 //oi.method(); Outer o = new Outer(); o.print(); } } class Outer { private int num = 10; private class Inner { //内部类私有 public void method() { System.out.println(num); } } public void print() { Inner i = new Inner(); // 外部类,提供内部类实例化方法 i.method(); } }
-
class Test1_InnerClass { public static void main(String[] args) { Outer.Inner oi = new Outer().new Inner(); oi.show(); } } //要求:使用已知的变量,在控制台输出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 Demo1_InnerClass { public static void main(String[] args) { //外部类名.内部类名 对象名 = 外部类名.内部类对象; Outer.Inner oi = new Outer.Inner(); oi.method(); Outer.Inner2.print(); } } class Outer { static class Inner { // 静态成员内部类 public void method() { System.out.println("method"); } } static class Inner2 { public static void print() { System.out.println("print"); } } }
-
-
局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么?
-
因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失。
-
那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了。
-
如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用。
-
-
-
class Demo1_InnerClass { public static void main(String[] args) { Outer o = new Outer(); o.method(); } } //局部内部类 class Outer { public void method() { final int num = 10; //int num = 10; 错误:从内部类中访问本地变量num;需要被声明为最终类型。final class Inner { // 局部内部类 public void print() { System.out.println(num); } } Inner i = new Inner(); //只能在局部所在的方法中访问 i.print(); } /*public void run() { Inner i = new Inner(); //局部内部类,只能在其所在的方法中访问 i.print(); }*/ }
- 匿名内部类
- 就是内部类的简化写法。
- 前提:
- 存在一个类或者接口
- 这里的类可以是具体类也可以是抽象类。
- 格式
-
new 类名或者接口名() {
重写方法;
}
-
-
class Demo1_NoNameInnerClass { public static void main(String[] args) { Outer o = new Outer(); o.method(); } } interface Inter { public void print(); } class Outer { /*class Inner implements Inter { // 这是有名字的内部类,继承Inter接口 public void print() { System.out.println("print"); } }*/ public void method(){ //Inner i = new Inner(); //i.print(); //new Inner().print(); //Inter i = new Inner(); //父类引用指向子类对象 new Inter() { //实现Inter接口 public void print() { //重写抽象方法 System.out.println("print"); } }.print(); // } }
-
class Demo2_NoNameInnerClass { public static void main(String[] args) { Outer o = new Outer(); o.method(); } } interface Inter { public void show1(); public void show2(); } //匿名内部类只针对重写一个方法时候使用 class Outer { public void method() { /*new Inter(){ public void show1() { System.out.println("show1"); } public void show2() { System.out.println("show2"); } }.show1(); new Inter(){ public void show1() { System.out.println("show1"); } public void show2() { System.out.println("show2"); } }.show2();*/ Inter i = new Inter(){ public void show1() { System.out.println("show1"); } public void show2() { System.out.println("show2"); } /*public void show3() { System.out.println("show3"); }*/ }; i.show1(); i.show2(); //i.show3(); //匿名内部类是不能向下转型的,因为没有子类类名 } }
-
- 匿名内部类在开发中的应用
-
class Test1_NoNameInnerClass { public static void main(String[] args) { //如何调用PersonDemo中的method方法呢? PersonDemo pd = new PersonDemo (); //pd.method(new Student()); pd.method(new Person() { public void show() { System.out.println("show"); } }); } } //这里写抽象类,接口都行 abstract class Person { public abstract void show(); } class PersonDemo { //public void method(Person p) { //Person p = new Student(); //父类引用指向子类对象 /* Person p = new Person(){ public void show() { System.out.println("show"); } }; */ public void method(Person p) { p.show(); } } class Student extends Person { public void show() { System.out.println("show"); } }
-
class Test2_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("HelloWorld"); } }; } } //要求在控制台输出”HelloWorld”
-