面向对象和面向过程
面向对象的好处
面向对象的思考步骤
对现实世界中,具有共同特性的某一类事物的抽象的描述,在Java中使用一个类来描述一类事物;
类是描述了一组有相同特性(属性)和相同行为(方法)的一组对象的集合。
类是构造面向对象程序的基本单位
类是对象的模板
//声明一个名称为 Person 的类。
public class Person {
// 类的主体
//类的属性
private String name; // 姓名
private int age; // 年龄
//类的无参构造器
public Person(){
}
//类的方法
public void tell() {
// 定义说话的方法
System.out.println(name+"今年"+age+"岁!");
}
}
说明:
类的访问控制符只能是空或者 public;每个 Java 程序的主类都必须是 public 类。
//创建一个子对象的调用过程
public void T1(){
public static void main(String[] args) {
System.out.println("77777777777777");
new Son();//输出结果顺序:3 6 7 2 1 5 4
System.out.println("=====================================");
new Son();//输出结果顺序:2 1 5 4
System.out.println("=====================================");
new Father();//输出结果顺序:2 1
}
}
//定义一个子类
public class Son extends Father {
public Son() {
System.out.println("4444444444");
}
{
System.out.println("555555555555");
}
static {
System.out.println("66666666666");
}
}
//定义一个父类
class Father {
{
System.out.println("22222222222");
}
public Father() {
System.out.println("11111111111");
}
static {
System.out.println("3333333333");
}
}
对象是类的一个具体的个体,是类的一个实例(instance);
对象是现实世界中实体的描述,对象要创建才存在,有了对象才能对对象进行操作;
创建对象的网络表达:
//方式1:
Cat cat = new Cat();
/*方式2:
语法格式;
java.lang.Class Class类对象名称 = java.lang.Class.forName(要实例化的类全称);
类名 对象名 = (类名)Class类对象名称.newInstance();
*/
/**
调用 java.lang.Class 类中的 forName() 方法时,需要将要实例化的类的全称(比如 com.mxl.package.Student)作为参数传递过去,然后再调用 java.lang.Class 类对象的 newInstance() 方法创建对象。
**/
Class c1 = Class.forName("package com.lhyedu.java.bean.Student");
Student student01 = (Student)c1.newInstance();
System.out.println(student01);
//方式2:
//获取构造方法并创建对象
Constructor c2 = c1.getDeclaredConstructor(String.class,String.class,int.class);
//根据构造方法创建对象并设置属性
Student student02 = (Student)c2.newInstance("张三","男",20);
System.out.println(student01);
//方式3:
/*
使用该方法创建对象时,要实例化的类必须继承 java.lang.Cloneable 接口;
不会调用类的构造方法,它会创建一个复制的对象,这个对象和原来的对象具有不同的内存地址,但它们的属性值相同;
调用对象的 clone() 方法创建对象的语法格式如下:
类名对象名 = (类名)已创建好的类对象名.clone();
*/
public class Student implements Cloneable {
// 实现 Cloneable 接口
}
// 调用对象的 clone() 方法创建对象
Student student3 = (Student)student2.clone();
System.out.println(student3);
//定义一个person类
public class Person {
int age = 90;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
//创建对象
Person person = new Person(20, "张三");
person.age = 22;
person.name = "jack";
说明:
每个对象都是相互独立的,在内存中占有独立的内存地址,并且每个对象都具有自己的生命周期;
当一个对象的生命周期结束时,对象就变成了垃圾,由 Java 虚拟机自带的垃圾回收机制处理。
Person p1 = new Person();
p1.age = 10 ;
p1.name = "小明";
Person p2 = p1;
class Person {
//四个属性
int age;
String name;
}
栈:
堆:
方法区(Method Area)
区别
关系
说明:
class Person {
//四个属性
int age;
String name;
double sal;
boolean isPass;
}
一个完整的方法通常包括方法名称、方法主体、方法参数和方法返回值类型;
方法:代表一个功能的定义,具有可重用性,就可以把这样的一段代码,抽象成一个方法;
public class Test {
[public|private|protected] [static] ([paramList]) {
// 方法主体
}
}
/*
说明
形参列表[paramList]
表示成员方法输入 cal(int n) , getSum(int num1, int num2)
可以有0个或多个参数,中间用逗号隔开
返回数据类型
表示成员方法输出, void 表示没有返回值
方法主体
表示为了实现某一功能代码块
return语句
不是必须
方法体
完成功能的具体语句
包括 输入、输出、变量、运算、分支、循环、方法调用
访问修饰符
public、private、protected:表示成员方法的访问权限
*/
说明:
方法只有被调用才会执行;
要不要传实参,看被调用的方法是否声明了形参;
一个方法最多有一个返回值;
方法不能嵌套定义方法
方法被static修饰时,称为类方法或静态方法
说明
递归就是方法自己调用自己,每次调用时传入不同的变量;
应用实例
//打印问题
public class Test {
public static void main(String[] args) {
T t1 = new T();
t1.test(4);//输出什么? n=2 n=3 n=4
int res = t1.factorial(5);
System.out.println("5的阶乘 res =" + res); //120
}
}
class T {
//分析
public void test(int n) {
if (n > 2) {
test(n - 1);
}
System.out.println("n=" + n);
}
//factorial 阶乘
public int factorial(int n) {
if (n == 1) {
return 1;
} else {
return factorial(n - 1) * n;
}
}
}
/*
猴子吃桃子问题:有一堆桃子,猴子第一天吃了其中的一半,并再多吃了一个!
以后每天猴子都吃其中的一半,然后再多吃一个。当到第 10 天时,
想再吃时(即还没吃),发现只有 1 个桃子了。问题:最初共多少个桃子?
*/
/*
思路分析 逆推
1. day = 10 时 有 1 个桃子
2. day = 9 时 有 (day10 + 1) * 2 = 4
3. day = 8 时 有 (day9 + 1) * 2 = 10
4. 规律就是 前一天的桃子 = (后一天的桃子 + 1) *2
5. 递归
*/
public int peach(int day) {
if(day == 10) {//第 10 天,只有 1 个桃
return 1;
} else if ( day >= 1 && day <=9 ) {
return (peach(day + 1) + 1) * 2;//规则
} else {
System.out.println("day 在 1-10");
return -1;
}
}
//迷宫问题
public class T2 {
@Test
public void t2() {
/*思路
1. 先创建迷宫,用二维数组表示 int[][] map = new int[8][7];
2. 先规定 map 数组的元素值: 0 表示可以走 1 表示障碍物
*/
int[][] map = new int[8][7];
// 3. 将最上面的一行和最下面的一行,全部设置为 1,作为边框
for (int i = 1; i < map[0].length; i++) {
map[0][i] = 1;
map[7][i] = 1;
}
// 4.将最右面的一列和最左面的一列,全部设置为 1
for (int i = 0; i < map.length - 1; i++) {
map[i][0] = 1;
map[i][6] = 1;
}
// 输出当前的地图
System.out.println("=====当前地图情况======");
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
System.out.print(map[i][j] + " ");// 输出一行
}
System.out.println();
}
// 使用 findWay 给老鼠找路
T t1 = new T();
// 下右上左的方向
t1.findWay(map, 1, 1);
System.out.println("\n====找路的情况如下=====");
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
System.out.print(map[i][j] + " ");// 输出一行
}
System.out.println();
}
}
class T {
/*
解读:
1. findWay 方法就是专门来找出迷宫的路径
2. 如果找到,就返回 true ,否则返回 false
3. map 就是二维数组,即表示迷宫
4. i,j 就是老鼠的位置,初始化的位置为(1,1)
5. 因为我们是递归的找路,所以我先规定 map 数组的各个值的含义: 0 表示可以走 1 表示障碍物 2 表示可以走 3 表示走过,但是走不通是死路
6. 当 map[6][5] =2表示终点,则找到出口,就可以结束,否则就继续找.
7. 先确定老鼠找路策略 下->右->上->左
*/
public boolean findWay(int[][] map, int i, int j) {
if (map[6][5] == 2) {
return true;
} else {
if (map[i][j] == 0) {// 当前这个位置 0,说明表示可以走
// 我们假定可以走通
map[i][j] = 2;
// 使用找路策略,来确定该位置是否真的可以走通
// 下->右->上->左
if (findWay(map, i + 1, j)) {// 先走下
return true;
} else if (findWay(map, i, j + 1)) {// 右
return true;
} else if (findWay(map, i - 1, j)) {// 上
return true;
} else if (findWay(map, i, j - 1)) {// 左
return true;
} else {
map[i][j] = 3;
return false;
}
} else { // map[i][j] = 1 , 2, 3
return false;
}
}
}
}
}
//汉诺塔
/*
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着 64 片圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
*/
//八皇后
/*
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于 1848 年提出:在 8× 8 格的国际象棋上摆放八个皇后,使其不能互相攻击,即:任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
*/
说明:
1)基本类型
public class MethodParameter01 {
//编写一个main方法
public static void main(String[] args) {
int a = 10;
int b = 20;
//创建AA对象 名字 obj
AA obj = new AA();
obj.swap(a, b); //调用swap
System.out.println("main方法 a=" + a + " b=" + b);//a=10 b=20
}
}
class AA {
public void swap(int a,int b){
System.out.println("\na和b交换前的值\na=" + a + "\tb=" + b);//a=10 b=20
//完成了 a 和 b的交换
int tmp = a;
a = b;
b = tmp;
System.out.println("\na和b交换后的值\na=" + a + "\tb=" + b);//a=20 b=10
}
}
2)引用类型
注意
p=null 和 p = new Person();
说明:
class TestReview{
//getVolume方法
public static int getVolume(int area, int height){
return area * height;
}
//getArea方法
public static double getArea(double lenght, double width){
return lenght * width;
}
public static void main(String[] args){
int a = 2;//长
int b = 3;//宽
int h = 4;//高
//把方法的返回值赋值给一个变量,变量area的类型要与方法getArea()的返回值类型 一致(或兼容)
double area = getArea(a,b);
//getArea(a,b)的返回值类型是double,而getVolume()的第一个形参是int
//int v = getVolume(getArea(a,b) ,h);//错误
//把方法的返回值 作为表达式的一部分
double v = getArea(a,b) * h;
}
}
说明:
public class VarParameter01 {
//编写一个main方法
public static void main(String[] args) {
HspMethod m = new HspMethod();
System.out.println(m.sum(1, 5, 100)); //106
System.out.println(m.sum(1,19)); //20
}
}
class HspMethod {
//可以计算 2个数的和,3个数的和 , 4. 5, 。。
//1. int... 表示接受的是可变参数,类型是int ,即可以接收多个int(0-多)
//2. 使用可变参数时,可以当做数组来使用 即 nums 可以当做数组
//3. 遍历 nums 求和即可
public int sum(int... nums) {
//System.out.println("接收的参数个数=" + nums.length);
int res = 0;
for(int i = 0; i < nums.length; i++) {
res += nums[i];
}
return res;
}
}
//找多个整数中的最大值,至少一个
int getMax(int a , int... b){
int max= a;
for(int num : b){
if(max
特点:
作用:
调用:
public class OverLoad01 {
//编写一个main方法
public static void main(String[] args) {
MyCalculator mc = new MyCalculator();
System.out.println(mc.calculate(1, 2));
System.out.println(mc.calculate(1.1, 2));
System.out.println(mc.calculate(1, 2.1));
}
}
class MyCalculator {
//下面的四个 calculate方法构成了重载
//两个整数的和
public int calculate(int n1, int n2) {
System.out.println("calculate(int n1, int n2) 被调用");
return n1 + n2;
}
//一个整数,一个double的和
public double calculate(int n1, double n2) {
return n1 + n2;
}
//一个double ,一个Int和
public double calculate(double n1, int n2) {
System.out.println("calculate(double n1, int n2) 被调用..");
return n1 + n2;
}
//三个int的和
public int calculate(int n1, int n2,int n3) {
return n1 + n2 + n2;
}
}
特点
细节
与重载的区别
说明:
//成员内部类
//1、定义
public class InnerClass01 {//外部其他类
public static void main(String[] args) {
}
}
class Outer {//外部类
private int n1 = 100;//属性
public Outer(int n1) {//构造器
this.n1 = n1;
}
public void m1() {//方法
System.out.println("m1()");
}
{//代码块
System.out.println("代码块...");
}
class inner {//成员内部类,在Outer类的内部
}
}
//访问
public class MemberInnerClass01 {//外部其他类
public static void main(String[] args) {
Outer08 outer08 = new Outer08();
outer08.t1();
//外部其他类,使用成员内部类的三种方式
// 第一种方式
// outer08.new Inner08(); 相当于把 new Inner08()当做是outer08成员
// 这就是一个语法,不要特别的纠结.
Outer08.Inner08 inner08 = outer08.new Inner08();
inner08.say();
System.out.println("=========================");
// 第二方式 在外部类中,编写一个方法,可以返回 Inner08对象
Outer08.Inner08 inner08Instance = outer08.getInner08Instance();
inner08Instance.say();
}
}
class Outer08 { //外部类
private int n1 = 10;
public String name = "张三";
private void hi() {
System.out.println("hi()方法...");
}
//1.注意: 成员内部类,是定义在外部内的成员位置上
//2.可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员
public class Inner08 {//成员内部类
private double sal = 99.8;
private int n1 = 66; //成员内部类的成员变量和外部类的成员变量重名
public void say() {
//可以直接访问外部类的所有成员,包含私有的
//如果成员内部类的成员变量和外部类的成员变量重名,会遵守就近原则
//可以通过 外部类名.this.属性 来访问外部类的成员变量
System.out.println("n1 = " + n1 + " name = " + name + " 外部类的n1=" + Outer08.this.n1);
//访问外部类的成员方法;
hi();
}
}
//外部类的成员方法,返回一个Inner08实例
public Inner08 getInner08Instance(){
return new Inner08();
}
//外部类的成员方法
public void t1() {
//使用成员内部类
//创建成员内部类的对象,然后使用相关的方法
Inner08 inner08 = new Inner08();
inner08.say();
System.out.println(inner08.sal);
}
}
/*
输出:
n1 = 66 name = 张三 外部类的n1=10
hi()方法...
99.8
n1 = 66 name = 张三 外部类的n1=10
hi()方法...
=========================
n1 = 66 name = 张三 外部类的n1=10
hi()方法...
*/
//静态内部类
//访问
public class StaticInnerClass01 {
public static void main(String[] args) {
Outer10 outer10 = new Outer10();
outer10.m1();//李四 外部类name= 张三
// 外部其他类 使用静态内部类
// 方式1
// 因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
Outer10.Inner10 inner10 = new Outer10.Inner10();
inner10.say();//李四 外部类name= 张三
// 方式2
// 编写一个方法,可以返回静态内部类的对象实例.
Outer10.Inner10 inner101 = outer10.getInner10();
System.out.println("============");
inner101.say();//李四 外部类name= 张三
Outer10.Inner10 inner10_ = Outer10.getInner10_();
System.out.println("************");
inner10_.say();//李四 外部类name= 张三
}
}
class Outer10 { // 外部类
private int n1 = 10;
private static String name = "张三";
private static void cry() {
}
static class Inner10 {//静态内部类
private static String name = "李四";
public void say() {
// 如果外部类和静态内部类的成员重名时;,静态内部类访问的时,默认遵循就近原则;
// 重名时,如果想访问外部类的静态成员,则可以使用 (外部类名.成员)
System.out.println(name + " 外部类name= " + Outer10.name);
//访问外部类的静态成员方法;
cry();
}
}
public void m1() {
// 外部类---访问------>静态内部类;访问方式:创建内部类对象,再访问
Inner10 inner10 = new Inner10();
inner10.say();
}
public Inner10 getInner10() {
return new Inner10();
}
public static Inner10 getInner10_() {
return new Inner10();
}
}
//局部内部类
//2、访问
public class LocalInterClass {
public static void main(String[] args) {
Outer02 outer02 = new Outer02();
outer02.m1();
System.out.println("outer02 的 hashcode=" + outer02);
}
}
class Outer02 {//外部类
private int n1 = 100;
private void m2() {//私有方法
System.out.println("Outer02 m2()");
}
public void m1() {//方法
//1.局部内部类是定义在外部类的局部位置,通常在方法中
//3.不能添加访问修饰符,但是可以使用 final 修饰
//4.作用域 : 仅仅在定义它的方法或代码块中
final class Inner02 {//局部内部类(本质仍然是一个类)
//2.可以直接访问外部类的所有成员,包含私有的
private int n1 = 800;
public void f1() {
//5. 局部内部类可以直接访问外部类的成员,比如下面 外部类 n1 和 m2()
//7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,使用外部类名.this.成员) 去访问
//解读: Outer02.this 本质就是外部类的对象, 即哪个对象调用了 m1, Outer02.this 就是哪个对象
System.out.println("n1=" + n1 + " 外部类的 n1=" + Outer02.this.n1);
System.out.println("Outer02.this hashcode=" + Outer02.this);
m2();
}
}
//6. 外部类在方法中,可以创建 Inner02 对象,然后调用方法即可
Inner02 inner02 = new Inner02();
inner02.f1();
}
}
/*
结果
n1=800 外部类的 n1=100
Outer02.this hashcode=com.hspedu.Outer02@14ae5a5
Outer02 m2()
outer02 的 hashcode=com.hspedu.Outer02@14ae5a5
*/
public class TestLocal {
//在外部类的外面,可以得到内部类的对象
public static void main(String[] args) {
MyInter m = new Out().test1();
Object obj = new Out().test2();
MyInter obj02 =(MyInter) new Out().test2();
}
}
interface MyInter {
void test01();
}
class Out {//外部类
// 使用父接口类型返回
public MyInter test1() {
class Inner implements MyInter {//局部内部类
@Override
public void test01() {
System.out.println("Inner01 = " + Inner.class);
}
}
return new Inner();
}
// 使用父类类型返回
public Object test2() {
class Inner implements MyInter {//局部内部类
@Override
public void test01() {
System.out.println("Inner02 = " + Inner.class);
}
}
return new Inner();
}
}
//匿名内部类
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
}
class Outer04 { // 外部类
private int n1 = 10;// 属性
public void method() {// 方法
// 基于接口的匿名内部类
// 1.需求: 想使用IA接口,并创建对象,且子类Tiger/Dog 类只是使用一次,后面再不使用
// 2. 可以使用匿名内部类来简化开发
// 3. tiger的编译类型 ? IA
// 4. tiger的运行类型 ? 就是匿名内部类 Outer04$1
/*
我们看底层 会分配 类名 Outer04$1
class Outer04$1 implements IA {
@Override
public void cry() {
System.out.println("老虎叫唤...");
}
}
*/
// 5. jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1实例,并且把地址返回给 tiger
IA tiger = new IA() {
@Override
public void cry_IA() {
System.out.println("老虎叫唤...");
}
};
System.out.println("tiger的运行类型=" + tiger.getClass());
tiger.cry_IA(); // 老虎叫唤...Outer04$1
tiger.cry_IA(); // 老虎叫唤...Outer04$1
tiger.cry_IA(); // 老虎叫唤...Outer04$1
// 演示基于类的匿名内部类
// 分析
// 1. father编译类型 Father
// 2. father运行类型 Outer04$2
// 3. 底层会创建匿名内部类
/*
class Outer04$2 extends Father{
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
}
*/
// 4. 同时也直接返回了 匿名内部类 Outer04$2的对象
// 5. 注意("jack") 参数列表会传递给 构造器
Father father = new Father("jack") {
@Override
public void test_Father() {
System.out.println("匿名内部类重写了test方法");
}
};
System.out.println("father对象的运行类型=" + father.getClass());// Outer04$2
father.test_Father();
// 基于抽象类的匿名内部类
Animal animal = new Animal() {
@Override
void eat_Animal() {
System.out.println("小狗吃骨头...");
}
};
animal.eat_Animal();// Outer04$3
}
}
interface IA {// 接口
public void cry_IA();
}
class Father {// 类
public Father(String name) {// 构造器
System.out.println("接收到name=" + name);
}
public void test_Father() {// 方法
}
}
abstract class Animal { // 抽象类
abstract void eat_Animal();
}
//匿名内部类的访问
package com.hspedu;
//匿名内部类的访问
public class AnonymousInnerClassDetail {
public static void main(String[] args) {
Outer05 outer05 = new Outer05();
outer05.f1();
// 外部其他类---不能访问----->匿名内部类
System.out.println("main outer05 hashcode=" + outer05);
}
}
class Outer05 {
private int n1 = 99;
public void f1() {
// 创建一个基于类的匿名内部类
Person p = new Person() {
private int n1 = 88;
@Override
public void hi() {
// 可以直接访问外部类的所有成员,包含私有的
// 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,
// 默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问
System.out.println("匿名内部类重写了 hi 方法 n1=" + n1 + " 外部内的 n1=" + Outer05.this.n1);
// Outer05.this 就是调用 f1 的 对象
System.out.println("Outer05.this hashcode=" + Outer05.this);
}
};
p.hi();// 动态绑定, 运行类型是 Outer05$1
// 也可以直接调用, 匿名内部类本身也是返回对象
// class 匿名内部类 extends Person {}
//调用匿名内部类的ok(str)方法
new Person() {
@Override
public void hi() {
System.out.println("匿名内部类重写了 hi 方法,哈哈...");
}
@Override
public void ok(String str) {
super.ok(str);
}
}.ok("jack");
//调用匿名内部类的hi()方法
new Person() {
@Override
public void hi() {
System.out.println("匿名内部类重写了 hi 方法,呵呵呵...");
}
@Override
public void ok(String str) {
super.ok(str);
}
}.hi();
}
}
class Person {// 类
//3个继承者
public void hi() {//3个重写
System.out.println("Person hi()");
}
public void ok(String str) {//2个重写
System.out.println("Person ok() " + str);
}
}
// 抽象类/接口...
/*
输出结果:
匿名内部类重写了 hi 方法 n1=88 外部内的 n1=99
Outer05.this hashcode=com.hspedu.Outer05@14ae5a5
Person ok() jack
匿名内部类重写了 hi 方法,呵呵呵...
main outer05 hashcode=com.hspedu.Outer05@14ae5a5
*/
//匿名内部类的使用01
/**
* 匿名内部类做实参直接传递;
*/
public class InnerClassExercise01 {
public static void main(String[] args) {
// 当做实参直接传递,简洁高效
f1(new IL() {
@Override
public void show() {
System.out.println("这是一副名画~~...");
}
});
// 传统方法
f1(new Picture());
}
// 静态方法,形参是接口类型
public static void f1(IL il) {
il.show();
}
}
// 接口
interface IL {
void show();//2个实现
}
// 类->实现 IL => 编程领域 (硬编码)
class Picture implements IL {
@Override
public void show() {
System.out.println("这是一副名画 XX...");
}
}
/*
结果输出:
这是一副名画~~...
这是一副名画 XX...
*/
/**
* 匿名内部类的使用02
* 1.有一个铃声接口 Bell,里面有个 ring 方法。
* 2.有一个手机类 Cellphone,具有闹钟功能 alarmClock,参数是 Bell 类型
* 3.测试手机类的闹钟功能,通过匿名内部类(对象)作为参数,打印:懒猪起床了
* 4.再传入另一个匿名内部类(对象),打印:该上学了
*/
public class AnonymousInnerTest02 {
public static void main(String[] args) {
Cellphone cellphone = new Cellphone();
// 1. 传递的是实现了 Bell 接口的匿名内部类 AnonymousInnerTest02$1
// 2. 重写了 ring
cellphone.alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("懒猪起床了");
}
});
cellphone.alarmClock(new Bell() {
@Override
public void ring() {
System.out.println("该上学了");
}
});
}
}
class Cellphone {//类
public void alarmClock(Bell bell) {///形参是 Bell 接口类型
System.out.println(bell.getClass());
bell.ring();// 动态绑定
}
}
interface Bell {//接口
void ring();//2个实现
}