7.面向对象进阶(1)
文章目录
- 一、复习
- 1.1 如何定义类
- 1.2 如何通过类创建对象
- 1.3 封装
- 1.3.1 封装的步骤
- 1.3.2 封装的步骤实现
- 1.4 构造方法
- 1.4.1 构造方法的作用
- 1.4.2 构造方法的格式
- 1.4.3 构造方法的应用
- 1.5 this关键字的作用
- 1.5.1 this关键字的作用
- 1.5.2 this关键字的应用
- 1.5.2.1 用于普通的gettter与setter方法
- 1.5.2.2 用于构造方法中
- 第二章 static关键字
- 2.1 概述
- 2.2 定义格式和使用
- 2.3 注意事项和小结
- 2.4 工具类
- 第三章 继承
- 3.1 概述
- 3.2 继承的特点
- 3.3 继承的格式
- 3.4 继承后的特点
- 3.4.1 成员变量
- 3.4.2 成员方法与方法重写
- @Override重写注解
- 3.4.3 构造方法
- 3.5 super(...)和this(...)
- 3.6 继承的特点
- 3. 7案例小结:
- 第四章 多态
- 4.1 多态的形式
- 4.2 多态的运行
- 4.2.1 多态的运行特点
- 4.2.2 多态的使用场景
- 4.2.3 引用类型转换:
- instanceof关键字
- instanceof新特性
- 代码
- 4.3 小结
- 4.4 案例
- 第五章 抽象类
- 5.1 abstract使用格式
- 5.2 抽象类的细节
- 5.3 案例
- 第六章 接口
- 6.1 接口的定义和使用
- 6.2 定义格式
- 6.3 接口成员的特点
- 6.4 接口与类之间的关系
- 6.5 案例:练习
- 6.6 JDK8开始接口中新增的方法
- 6.6.1 新增的方法
- 案例一:接口的方法不重写
- 案例二:接口的方法重写
- 6.6.2 新增的静态方法
- 6.6.3 JDK9以后新增加的方法
- 6.7 接口的应用
- 6.8适配器设计模式
- 第七章 内部类
- 7.1 概述
- 7.2 内部类的分类
- 7.3 成员内部类
- 7.4 成员内部类面试题
- 7.5 静态内部类
- 7.6 局部内部类
- 7.7 匿名内部类
- 案例
- 案例2
一、复习
1.1 如何定义类
类的定义格式如下:
修饰符 class 类名 {// 1.成员变量(属性)// 2.成员方法 (行为) // 3.构造方法 (初始化类的对象数据的)
}
例如:
public class Student {// 1.成员变量public String name ;public char sex ; // '男' '女'public int age;
}
1.2 如何通过类创建对象
类名 对象名称 = new 类名();
例如:
Student stu = new Student();
1.3 封装
1.3.1 封装的步骤
1.使用 private
关键字来修饰成员变量。
2.使用public
修饰getter和setter方法。
1.3.2 封装的步骤实现
- private修饰成员变量
public class Student {private String name;private int age;
}
- public修饰getter和setter方法
public class Student {private String name;private int age;public void setName(String n) {name = n;}public String getName() {return name;}public void setAge(int a) {if (a > 0 && a <200) {age = a;} else {System.out.println("年龄非法!");}}public int getAge() {return age;}
}
1.4 构造方法
1.4.1 构造方法的作用
在创建对象的时候,给成员变量进行初始化。
初始化即赋值的意思。
1.4.2 构造方法的格式
修饰符 类名(形参列表) {// 构造体代码,执行代码
}
1.4.3 构造方法的应用
首先定义一个学生类,代码如下:
public class Student {// 1.成员变量public String name;public int age;// 2.构造方法public Student() {System.out.println("无参数构造方法被调用");}
}
接下来通过调用构造方法得到两个学生对象。
public class CreateStu02 {public static void main(String[] args) {// 创建一个学生对象// 类名 变量名称 = new 类名();Student s1 = new Student();// 使用对象访问成员变量,赋值s1.name = "张三";s1.age = 20 ;// 使用对象访问成员变量 输出值System.out.println(s1.name);System.out.println(s1.age); Student s2 = new Student();// 使用对象访问成员变量 赋值s2.name = "李四";s2.age = 18 ;System.out.println(s2.name);System.out.println(s2.age);}
}
1.5 this关键字的作用
1.5.1 this关键字的作用
this代表所在类的当前对象的引用(地址值),即代表当前对象。
1.5.2 this关键字的应用
1.5.2.1 用于普通的gettter与setter方法
this出现在实例方法中,谁调用这个方法(哪个对象调用这个方法),this就代表谁(this就代表哪个对象)。
public class Student {private String name;private int age;public void setName(String name) {this.name = name;}public String getName() {return name;}public void setAge(int age) {if (age > 0 && age < 200) {this.age = age;} else {System.out.println("年龄非法!");}}public int getAge() {return age;}
}
1.5.2.2 用于构造方法中
this出现在构造方法中,代表构造方法正在初始化的那个对象。
public class Student {private String name;private int age;// 无参数构造方法public Student() {} // 有参数构造方法public Student(String name,int age) {this.name = name;this.age = age; }
}
第二章 static关键字
2.1 概述
Java中成员(变量和方法)等是存在所属性的,Java是通过static关键字来区分的。**static关键字在Java开发非常的重要,对于理解面向对象非常关键。
关于 static
关键字的使用,它可以用来修饰的成员变量和成员方法,被static修饰的成员是属于类的是放在静态区中,没有static修饰的成员变量和方法则是属于对象的。我们上面案例中的成员变量都是没有static修饰的,所以属于每个对象。
2.2 定义格式和使用
static是静态的意思。 static可以修饰成员变量或者修饰方法。
定义格式
修饰符 static 数据类型 变量名 = 初始值;
举例
public class Student {public static String schoolName = "传智播客"; // 属于类,只有一份。// .....public static void study(){System.out.println("我们都在黑马程序员学习"); }
}
静态成员变量的访问:
格式:类名.静态变量
格式:类名.静态方法
public static void main(String[] args){System.out.println(Student.schoolName); // 传智播客Student.schoolName = "黑马程序员";System.out.println(Student.schoolName); // 黑马程序员Student.study();
}
无static修饰的成员方法属于每个对象的,这个成员方法也叫做实例方法。
需要注意的是:实例方法是属于每个对象,必须创建类的对象才可以访问。
格式:对象.实例方法
示例:
public class Student {// 实例变量private String name ;// 2.方法:行为// 无 static修饰,实例方法。属于每个对象,必须创建对象调用public void run(){System.out.println("学生可以跑步");}// 无 static修饰,实例方法public void sleep(){System.out.println("学生睡觉");}public static void study(){}
}
public static void main(String[] args){// 创建对象 Student stu = new Student ;stu.name = "徐干";// Student.sleep();// 报错,必须用对象访问。stu.sleep();stu.run();
}
2.3 注意事项和小结
static的注意事项
- 静态方法只能访问静态变量和静态方法
- 非静态方法可以访问静态变量或者静态方法,也可以访问非静态的成员变量和非静态的成员方法
- 静态方法中是没有this关键字
- 总结:
- 静态方法中,只能访问静态。
- 非静态方法可以访问所有。
- 静态方法中没有this关键字
小结:
1.当 static
修饰成员变量或者成员方法时,该变量称为静态变量,该方法称为静态方法。该类的每个对象都共享同一个类的静态变量和静态方法。任何对象都可以更改该静态变量的值或者访问静态方法。但是不推荐这种方式去访问。因为静态变量或者静态方法直接通过类名访问即可,完全没有必要用对象去访问。
2.无static修饰的成员变量或者成员方法,称为实例变量,实例方法,实例变量和实例方法必须创建类的对象,然后通过对象来访问。
3.static修饰的成员属于类,会存储在静态区,是随着类的加载而加载的,且只加载一次,所以只有一份,节省内存。存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。它优先于对象存在,所以,可以被所有对象共享。
4.无static修饰的成员,是属于对象,对象有多少个,他们就会出现多少份。所以必须由对象调用。
2.4 工具类
不是用来描述一类事物的,而是帮我们做一些事情的类。
- 类名见名知意
- 私有化构造方法
- 方法定义为静态
工具类:
public class ArrayUtil {//私有化构造方法//目的:为了不让外界创建他的对象private ArrayUtil() {}//需要定义为静态的,方便调用public static String printArr(int[] arr) {StringBuilder sb = new StringBuilder();sb.append("[");for (int i = 0; i < arr.length; i++) {//i 索引 arr[i] 元素if (i == arr.length - 1) {sb.append(arr[i]);} else {sb.append(arr[i]).append(", ");}}sb.append("]");return sb.toString();}public static double getAverage(double[] arr) {double sum = 0;for (int i = 0; i < arr.length; i++) {sum = sum + arr[i];}return sum / arr.length;}}
测试类:
public class TestDemo {public static void main(String[] args) {//测试工具类中的两个方法是否正确int[] arr1 = {1, 2, 3, 4, 5};//直接就是:类名.f方法String str = ArrayUtil.printArr(arr1);System.out.println(str);double[] arr2 = {1.5, 3.7, 4.9, 5.8, 6.6};double avg = ArrayUtil.getAverage(arr2);System.out.println(avg);}
}
第三章 继承
3.1 概述
1.什么是继承、继承的好处?
继承是面向对象三大特征之一,可以让类跟类之间产生子父的关系。
继承**:就是子类继承父类的属性和行为,使得子类对象可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。
可以把多个子类中重复的代码抽取到父类中,子类可以直接使用,减少代码冗余,提高代码的复用性
提高代码的复用性(减少代码冗余,相同代码重复利用)。使类与类之间产生了关系。
2.继承的格式?
public class 子类 extends 父类{}
3.继承后子类的特点?
子类可以得到父类的属性和行为,子类可以使用。
子类可以在父类的基础上新增其他功能,子类更强大。继承的好处
3.2 继承的特点
- **JAVA只能单继承:**一个类只能继承一个直接父类。
- JAVA不支持多继承、但是支持多层继承。
- JAVA中所有的类都直接或者间接继承于对象类。
- Java中所有的类都直接或者间接继承于Object类。
- 子类只能访问父类中非私有的成员
子类不能继承的内容
- 子类不能继承父类的构造方法。
- 值得注意的是子类可以继承父类的私有成员(成员变量,方法),只是子类无法直接访问而已,可以通过getter/setter方法访问父类的private成员变量。
3.3 继承的格式
通过 extends
关键字,可以声明一个子类继承另外一个父类,定义格式如下:
class 父类 {...
}class 子类 extends 父类 {...
}
需要注意:Java是单继承的,一个类只能继承一个直接父类,跟现实世界很像,但是Java中的子类是更加强大的。
3.4 继承后的特点
3.4.1 成员变量
成员变量不重名:如果子类父类中出现不重名的成员变量,这时的访问是没有影响的。
成员变量重名:如果子类父类中出现重名的成员变量,这时的访问是有影响的。
super访问父类成员变量
1.继承中成员变量访问特点:就近原则。
先在局部位置找,本类成员位置找,父类成员位置找,逐级往上。
2.如果出现了重名的成员变量怎么办?
system.out.println(name); //从局部位置开始往上找
system.out.println(this.name) ; //从本类成员位置开始往上找
system.out.println(super.name); //从父类成员位置开始往上找
public class Test {public static void main(String[] args) {Zi z = new Zi();z.show();}
}class Fu {String name = "Fu";String hobby = "喝茶";}class Zi extends Fu {String name = "Zi";String game = "吃鸡";public void show() {//如何打印Zi//System.out.println(name);//Zi//System.out.println(this.name);//Zi//如何打印Fu//System.out.println(super.name);//Fu//如何打印喝茶//System.out.println(hobby);//喝茶//System.out.println(this.hobby);//喝茶//System.out.println(super.hobby);//喝茶//如何打印吃鸡System.out.println(game);System.out.println(this.game);}
}
3.4.2 成员方法与方法重写
方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现。
方法重写注意事项和要求:
- 1.重写方法的名称、形参列表必须与父类中的一致。
- 2.子类重写父类方法时,访问权限子类必须大于等于父类(暂时了解︰空着不写< protected<public)
- 3.子类重写父类方法时,返回值类型子类必须小于等于父类
- 4.建议:重写的方法尽量和父类保持一致。
- 5.只有被添加到虚方法表中的方法才能被重写
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0qgK2CFe-1665577746271)(E:\java\Java基础\图片\7\5.png)]
public class Test {public static void main(String[] args) {OverseasStudent s = new OverseasStudent();s.lunch();}
}class Person {public void eat() {System.out.println("吃米饭,吃菜");}public void drink() {System.out.println("喝开水");}
}//留学生
class OverseasStudent extends Person{public void lunch(){this.eat();//吃意大利面this.drink();//喝凉水super.eat();//吃米饭,吃菜super.drink();//喝开水}//应用场景:当父类中方法,不能满足子类现在的需求时,我们就需要把这个方法进行重写。//注意:子类中重写的方法上面需要加上@override@Overridepublic void eat() {System.out.println("吃意大利面");}@Overridepublic void drink() {System.out.println("喝凉水");}}class Student extends Person{public void lunch(){//先在本类中查看eat和drink方法,就会调用子类的,如果没有,就会调用从父类中继承下来的eat和drink方法this.eat();this.drink();//直接调用父类中的eat和drink方法super.eat();super.drink();}}
@Override重写注解
- @Override:注解,重写注解校验!
- 这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。
- 建议重写都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!
3.4.3 构造方法
继承中:构造方法的访问特点
- 父类中的构造方法不会被子类继承。
- 子类中所有的构造方法默认先访问父类中的无参构造,再执行自己。
为什么?
- 子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
- 子类初始化之前,一定要调用父类构造方法先完成父类数据空间的初始化。
怎么调用父类构造方法的?
- 子类构造方法的第一行语句默认都是:super(),不写也存在,且必须在第一行。
- 如果想调用父类有参构造,必须手动写super进行调用。
public class Person {String name;int age;public Person() {System.out.println("父类的无参构造");}public Person(String name, int age) {this.name = name;this.age = age;}
}public class Student extends Person{public Student(){//子类构造方法中隐藏的super()去访问父类的无参构造super();System.out.println("子类的无参构造");}public Student(String name,int age){super(name,age);}
}public class Test {public static void main(String[] args) {//创建学生对象//有参:经过有参构造方法,就不经过Student s = new Student("zhangsan",23);//无参:经过无参构造方法Student s = new Student();//输出: 父类的无参构造 子类的无参构造}
}
代码如下:
class Person {private String name;private int age;public Person() {System.out.println("父类无参");}// getter/setter省略
}class Student extends Person {private double score;public Student() {//super(); // 调用父类无参,默认就存在,可以不写,必须再第一行System.out.println("子类无参");}public Student(double score) {//super(); // 调用父类无参,默认就存在,可以不写,必须再第一行this.score = score; System.out.println("子类有参");}}public class Demo07 {public static void main(String[] args) {Student s1 = new Student();System.out.println("----------");Student s2 = new Student(99.9);}
}输出结果:
父类无参
子类无参
----------
父类无参
子类有参
3.5 super(…)和this(…)
super和this的用法格式
super和this完整的用法如下,其中this,super访问成员我们已经接触过了。
this.成员变量 -- 本类的
super.成员变量 -- 父类的this.成员方法名() -- 本类的
super.成员方法名() -- 父类的
接下来我们使用调用构造方法格式:
super(...) -- 调用父类的构造方法,根据参数匹配确认
this(...) -- 调用本类的其他构造方法,根据参数匹配确认
小结
- 子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。
- super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。
- super(…)和this(…)是根据参数去确定调用父类哪个构造方法的。
- super(…)可以调用父类构造方法初始化继承自父类的成员变量的数据。
- this(…)可以调用本类中的其他构造方法。
public class Student {String name;int age;String school;//需求://默认为传智大学public Student() {//表示调用本类其他构造方法//细节:虚拟机就不会再添加super();this(null,0,"传智大学");}public Student(String name, int age, String school) {this.name = name;this.age = age;this.school = school;}
}public class Test {public static void main(String[] args) {Student s = new Student();}
}
3.6 继承的特点
- Java只支持单继承,不支持多继承。
// 一个类只能有一个父类,不可以有多个父类。
class A {}
class B {}
class C1 extends A {} // ok
// class C2 extends A, B {} // error
- 一个类可以有多个子类。
// A可以有多个子类
class A {}
class C1 extends A {}
class C2 extends A {}
- 可以多层继承。
class A {}
class C1 extends A {}
class D extends C1 {}
顶层父类是Object类。所有的类默认继承Object,作为父类。
3. 7案例小结:
会写一个继承结构下的标准Javabean即可
需求:
猫:属性,姓名,年龄,颜色
狗:属性,姓名,年龄,颜色,吼叫
分享书写技巧:
1.在大脑中要区分谁是父,谁是子
2.把共性写到父类中,独有的东西写在子类中
3.开始编写标准Javabean(从上往下写)
4.在测试类中,创建对象并赋值调用
代码示例:
package com.itheima.test4;public class Animal {//姓名,年龄,颜色private String name;private int age;private String color;public Animal() {}public Animal(String name, int age, String color) {this.name = name;this.age = age;this.color = color;}//get和set方法
}public class Cat extends Animal{//因为猫类中没有独有的属性。//所以此时不需要写私有的成员变量//空参public Cat() {}//需要带子类和父类中所有的属性public Cat(String name, int age, String color) {super(name,age,color);}
}public class Dog extends Animal{//Dog :吼叫private String wang;//构造public Dog() {}//带参构造:带子类加父类所有的属性public Dog(String name, int age, String color,String wang) {//共性的属性交给父类赋值super(name,age,color);//独有的属性自己赋值this.wang = wang;}public String getWang() {return wang;}public void setWang(String wang) {this.wang = wang;}
}public class Demo {public static void main(String[] args) {//Animal : 姓名,年龄,颜色//Cat ://Dog :吼叫//创建狗的对象Dog d = new Dog("旺财",2,"黑色","嗷呜~~");System.out.println(d.getName()+", " + d.getAge() + ", " + d.getColor() + ", " + d.getWang());//创建猫的对象Cat c = new Cat("中华田园猫",3,"黄色");System.out.println(c.getName() + ", " + c.getAge() + ", " + c.getColor());}
}
第四章 多态
4.1 多态的形式
多态是继封装、继承之后,面向对象的第三大特性。
多态是出现在继承或者实现关系中的。
多态体现的格式:
父类类型 变量名 = new 子类/实现类构造器;
变量名.方法名();
多态的前提:
- 有继承关系,子类对象是可以赋值给父类类型的变量。例如Animal是一个动物类型,而Cat是一个猫类型。Cat继承了Animal,Cat对象也是Animal类型,自然可以赋值给父类类型的变量。
- 有继承/实现关系
- 有父类引用指向子类对象
- 有方法的重写
多态的好处:
- 使用父类型作为参数,可以接受所有子类对象
- 体现多态的扩展性与便利
4.2 多态的运行
4.2.1 多态的运行特点
调用成员变量时:编译看左边,运行看左边
调用成员方法时:编译看左边,运行看右边
代码示例:
Fu f = new Zi();
//编译看左边的父类中有没有name这个属性,没有就报错
//在实际运行的时候,把父类name属性的值打印出来
System.out.println(f.name);
//编译看左边的父类中有没有show这个方法,没有就报错
//在实际运行的时候,运行的是子类中的show方法
f.show();
4.2.2 多态的使用场景
父类:
public class Person {private String name;private int age;空参构造带全部参数的构造get和set方法public void show(){System.out.println(name + ", " + age);}
}子类1:
public class Administrator extends Person {@Overridepublic void show() {System.out.println("管理员的信息为:" + getName() + ", " + getAge());}
}子类2:
public class Student extends Person{@Overridepublic void show() {System.out.println("学生的信息为:" + getName() + ", " + getAge());}
}子类3:
public class Teacher extends Person{@Overridepublic void show() {System.out.println("老师的信息为:" + getName() + ", " + getAge());}
}测试类:
public class Test {public static void main(String[] args) {//创建三个对象,并调用register方法Student s = new Student();s.setName("张三");s.setAge(18);Teacher t = new Teacher();t.setName("王建国");t.setAge(30);Administrator admin = new Administrator();admin.setName("管理员");admin.setAge(35);register(s);register(t);register(admin);}//这个方法既能接收老师,又能接收学生,还能接收管理员//只能把参数写成这三个类型的父类public static void register(Person p){p.show();}
}
4.2.3 引用类型转换:
- 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。
使用格式:
子类类型 变量名 = (子类类型) 父类变量名;
如:Aniaml a = new Cat();Cat c =(Cat) a;
instanceof关键字
为了避免ClassCastException的发生,Java提供了 instanceof
关键字,给引用变量做类型的校验,格式如下:
变量名 instanceof 数据类型
如果变量属于该数据类型或者其子类类型,返回true。
如果变量不属于该数据类型或者其子类类型,返回false。
public class Test {public static void main(String[] args) {// 向上转型 Animal a = new Cat(); a.eat(); // 调用的是 Cat 的 eat// 向下转型 if (a instanceof Cat){Cat c = (Cat)a; c.catchMouse(); // 调用的是 Cat 的 catchMouse} else if (a instanceof Dog){Dog d = (Dog)a; d.watchHouse(); // 调用的是 Dog 的 watchHouse}}
}
instanceof新特性
JDK14的时候提出了新特性,把判断和强转合并成了一行
//新特性
//先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d
//如果不是,则不强转,结果直接是false
if(a instanceof Dog d){d.lookHome();
}else if(a instanceof Cat c){c.catchMouse();
}else{System.out.println("没有这个类型,无法转换");
}
代码
public class Test {public static void main(String[] args) {//创建对象Animal a = new Dog();//编译看左边,运行看右边a.eat();//多态的弊端//不能调用子类的特有功能//报错的原因?//当调用成员方法的时候,编译看左边,运行看右边//那么在编译的时候会先检查左边的父类中有没有这个方法,如果没有直接报错。//a.lookHome();//解决方案://变回子类类型就可以了//细节:转换的时候不能瞎转,如果转成其他类的类型,就会报错//Cat c = (Cat) a;//c.catchMouse();if(a instanceof Dog){Dog d = (Dog) a;d.lookHome();}else if(a instanceof Cat){Cat c = (Cat) a;c.catchMouse();}else{System.out.println("没有这个类型,无法转换");}// //新特性
// //先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d
// //如果不是,则不强转,结果直接是false
// if(a instanceof Dog d){// d.lookHome();
// }else if(a instanceof Cat c){// c.catchMouse();
// }else{// System.out.println("没有这个类型,无法转换");
// }}
}class Animal{public void eat(){System.out.println("动物在吃东西");}
}class Dog extends Animal{@Overridepublic void eat() {System.out.println("狗吃骨头");}public void lookHome(){System.out.println("狗看家");}
}class Cat extends Animal{@Overridepublic void eat() {System.out.println("猫吃小鱼干");}public void catchMouse(){System.out.println("猫抓老鼠");}
}
4.3 小结
1.多态的优势
方法中,使用父类型作为参数,可以接收所有子类对象
2.多态的弊端是什么?
不能使用子类的特有功能
3.引用数据类型的类型转换,有几种方式?
自动类型转换、强制类型转换
Person p = new Student ();
student s = (student)p;
4.强制类型转换能解决什么问题?
- 可以转换成真正的子类类型,从而调用子类独有功能。
- 转换类型与真实对象类型不一致会报错
- 转换的时候用instanceof关键字进行判断
4.4 案例
需求:根据需求完成代码:1.定义狗类属性:年龄,颜色行为:eat(String something)(something表示吃的东西)看家lookHome方法(无参数)
2.定义猫类属性:年龄,颜色行为:eat(String something)方法(something表示吃的东西)逮老鼠catchMouse方法(无参数)
3.定义Person类//饲养员属性:姓名,年龄行为:keepPet(Dog dog,String something)方法功能:喂养宠物狗,something表示喂养的东西行为:keepPet(Cat cat,String something)方法功能:喂养宠物猫,something表示喂养的东西生成空参有参构造,set和get方法
4.定义测试类(完成以下打印效果):keepPet(Dog dog,String somethind)方法打印内容如下:年龄为30岁的老王养了一只黑颜色的2岁的狗2岁的黑颜色的狗两只前腿死死的抱住骨头猛吃keepPet(Cat cat,String somethind)方法打印内容如下:年龄为25岁的老李养了一只灰颜色的3岁的猫3岁的灰颜色的猫眯着眼睛侧着头吃鱼
5.思考: 1.Dog和Cat都是Animal的子类,以上案例中针对不同的动物,定义了不同的keepPet方法,过于繁琐,能否简化,并体会简化后的好处?2.Dog和Cat虽然都是Animal的子类,但是都有其特有方法,能否想办法在keepPet中调用特有方法?
//动物类(父类)
public class Animal {private int age;private String color;public Animal() {}public Animal(int age, String color) {this.age = age;this.color = color;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public void eat(String something){System.out.println("动物在吃" + something);}
}//猫类(子类)
public class Cat extends Animal {public Cat() {}public Cat(int age, String color) {super(age, color);}@Overridepublic void eat(String something) {System.out.println(getAge() + "岁的" + getColor() + "颜色的猫眯着眼睛侧着头吃" + something);}public void catchMouse(){System.out.println("猫抓老鼠");}}//狗类(子类)
public class Dog extends Animal {public Dog() {}public Dog(int age, String color) {super(age, color);}//行为//eat(String something)(something表示吃的东西)//看家lookHome方法(无参数)@Overridepublic void eat(String something) {System.out.println(getAge() + "岁的" + getColor() + "颜色的狗两只前腿死死的抱住" + something + "猛吃");}public void lookHome(){System.out.println("狗在看家");}
}//饲养员类
public class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//饲养狗/* public void keepPet(Dog dog, String something) {System.out.println("年龄为" + age + "岁的" + name + "养了一只" + dog.getColor() + "颜色的" + dog.getAge() + "岁的狗");dog.eat(something);}//饲养猫public void keepPet(Cat cat, String something) {System.out.println("年龄为" + age + "岁的" + name + "养了一只" + cat.getColor() + "颜色的" + cat.getAge() + "岁的猫");cat.eat(something);}*///想要一个方法,能接收所有的动物,包括猫,包括狗//方法的形参:可以写这些类的父类 Animalpublic void keepPet(Animal a, String something) {if(a instanceof Dog d){System.out.println("年龄为" + age + "岁的" + name + "养了一只" + a.getColor() + "颜色的" + a.getAge() + "岁的狗");d.eat(something);}else if(a instanceof Cat c){System.out.println("年龄为" + age + "岁的" + name + "养了一只" + c.getColor() + "颜色的" + c.getAge() + "岁的猫");c.eat(something);}else{System.out.println("没有这种动物");}}
}//测试类
public class Test {public static void main(String[] args) {//创建对象并调用方法/* Person p1 = new Person("老王",30);Dog d = new Dog(2,"黑");p1.keepPet(d,"骨头");Person p2 = new Person("老李",25);Cat c = new Cat(3,"灰");p2.keepPet(c,"鱼");*///创建饲养员的对象Person p = new Person("老王",30);Dog d = new Dog(2,"黑");Cat c = new Cat(3,"灰");p.keepPet(d,"骨头");p.keepPet(c,"鱼");}
}
第五章 抽象类
1.抽象类的作用是什么样的?
抽取共性时,无法确定方法体,就把方法定义为抽象的。强制让子类按照某种格式重写。
抽象方法所在的类,必须是抽象类。
2.继承抽象类有哪些要注意?
- 要么重写抽象类中的所有抽象方法
- 要么是抽象类
3. 抽象类和抽象方法的注意事项
- 抽象类不能实例化
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类可以有构造方法
- 抽象类的子类
- 要么重写抽象类中的所有抽象方法
- 要么是抽象类
5.1 abstract使用格式
abstract是抽象的意思,用于修饰方法方法和类,修饰的方法是抽象方法,修饰的类是抽象类。
抽象方法
使用abstract
关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。
定义格式:
修饰符 abstract 返回值类型 方法名 (参数列表);
//代码举例:
public abstract void run();
抽象类
如果一个类包含抽象方法,那么该类必须是抽象类。注意:抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象类。
定义格式:
abstract class 类名字 { }
//代码举例:
public abstract class Animal {public abstract void run();
}
抽象类的使用
要求:继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类。
5.2 抽象类的细节
不需要背,只要当idea报错之后,知道如何修改即可。
关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。
抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
抽象类存在的意义是为了被子类继承。
理解:抽象类中已经实现的是模板中确定的成员,抽象类不确定如何实现的定义成抽象方法,交给具体的子类去实现。
5.3 案例
public abstract class Person {private String name;private int age;//作用:当创建子类对象的时,给属性进行赋值的。public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}//get和set方法//抽象方法public abstract void work();public void sleep(){System.out.println("睡觉");}}
public abstract class Teacher extends Person{}public class Student extends Person{//构造方法public Student() {}public Student(String name, int age) {super(name, age); //赋值父类}@Overridepublic void work() {System.out.println("学生的工作是学习");}
}public class ATeacher extends Teacher{@Overridepublic void work() {}
}
public class Test {public static void main(String[] args) {//创建对象// 创建抽象类,抽象类不能创建对象//Person p = new Person();Student s = new Student("zhangsan",23);System.out.println(s.getName() + ", " + s.getAge());}
}
第六章 接口
6.1 接口的定义和使用
接口用关键字interface来定义
public interface 接口名{}
接口不能实例化(创建对象)
接口和类之间是实现关系,通过implements关键字表示
public class 类名 implements 接口名{}
- 接口的子类(实现类)
- 要么重写接口中的所有抽象方法
- 要么是抽象类
**注意1:**接口和类的实现关系,可以单实现,也可以多实现。
public class 类名 implements 接口名1,接口名2{}
**注意2:**实现类还可以在继承一个类的同时实现多个接口。
public class 类名 extends 父类 implements 接口名1,接口名2{}
6.2 定义格式
//接口的定义格式:
interface 接口名称{// 抽象方法
}// 接口的声明:interface
// 接口名称:首字母大写,满足“驼峰模式”/**接口的实现:在Java中接口是被实现的,实现接口的类称为实现类。实现类的格式:*/
class 类名 implements 接口1,接口2,接口3...{}
6.3 接口成员的特点
public interface InterF {// 抽象方法!// public abstract void run();void run();// public abstract String getName();String getName();// public abstract int add(int a , int b);int add(int a , int b);// 它的最终写法是:// public static final int AGE = 12 ;int AGE = 12; //常量String SCHOOL_NAME = "黑马程序员";}
6.4 接口与类之间的关系
类和类的关系
继承关系,只能单继承,不能多继承,但是可以多层继承类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
接口和接口的关系
继承关系,可以单继承,也可以多继承
public interface Abc {void go();void test();
}/** 法律规范:接口*/
public interface Law {void rule();void test();
}** 总结:* 接口与类之间是多实现的。* 接口与接口之间是多继承的。* */
public interface SportMan extends Law , Abc {void run();
}
6.5 案例:练习
练习编写带有接口和抽象类的标准Javabean类
我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。为了出国交流,跟乒乓球相关的人员都需要学习英语。
请用所有知识分析,在这个案例中,哪些是具体类,哪些是抽象类,哪些是接口?
乒乓球运动员:姓名,年龄,学打乒乓球,说英语
篮球运动员:姓名,年龄,学打篮球
乒乓球教练:姓名,年龄,教打乒乓球,说英语
篮球教练:姓名,年龄,教打篮球
方法一:
方法二:我们采用的
代码复现:
父类:
//因为现在我不想让外界去直接创建人的对象
//因为直接创建顶层父类人的对象此时是没有意义的
//所以我就把他写为抽象的。
public abstract class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}//set和get方法
}
第二层
接口:
public interface English {public abstract void speakEnglish();//如果implement这个接口后,接口中的方法必须全部重载,要不然或报错//public void speak1(); //=public abstract void speak1();
}
javabean类
//运动员类
public abstract class Sporter extends Person{public Sporter() {}public Sporter(String name, int age) {super(name, age);}public abstract void study();
}//教练类
public abstract class Coach extends Person{public Coach() {}public Coach(String name, int age) {super(name, age);}public abstract void teach();
}//乒乓球运动员
public class PingPangSporter extends Sporter implements English{public PingPangSporter() {}public PingPangSporter(String name, int age) {super(name, age);}@Overridepublic void speakEnglish() {System.out.println("乒乓球运动员在说英语");}@Overridepublic void study() {System.out.println("乒乓球运动员在学习如何打乒乓球");}
}//乒乓球教练
public class PingPangCoach extends Coach implements English{public PingPangCoach() {}public PingPangCoach(String name, int age) {super(name, age);}@Overridepublic void teach() {System.out.println("乒乓球教练正在教如何打乒乓球");}@Overridepublic void speakEnglish() {System.out.println("乒乓球教练在学习说英语");}
}//
public class BasketballCoach extends Coach{public BasketballCoach() {}public BasketballCoach(String name, int age) {super(name, age);}@Overridepublic void teach() {System.out.println("篮球教练正在教如何打篮球");}
}//
public class BasketballSporter extends Sporter{public BasketballSporter() {}public BasketballSporter(String name, int age) {super(name, age);}@Overridepublic void study() {System.out.println("篮球运动员在学习如何打篮球");}
}
测试:
public class Test {public static void main(String[] args) {//创建运动员或教练的对象PingPangSporter pps = new PingPangSporter("刘诗雯",23);System.out.println(pps.getName() + ", " + pps.getAge());pps.study();pps.speakEnglish();}
}
6.6 JDK8开始接口中新增的方法
- JDK7以前:接口中只能定义抽象方法。
- JDK8:接口中可以定义有方法体的方法。(默认、静态)
- JDK9:接口中可以定义私有方法。
- 私有方法分为两种:普通的私有方法,静态的私有方法
6.6.1 新增的方法
允许在接口中定义默认方法,需要使用关键字default修饰
作用:解决接口升级的问题
接口中默认方法的定义格式:
格式: public default 返回值类型 方法名(参数列表){}范例: public default void show(){ }
- 接口中默认方法的注意事项:
- 默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉default关键字
- public可以省略,default不能省略
- 如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写
案例一:接口的方法不重写
//接口A
public interface InterA {public abstract void method();public default void show(){System.out.println("InterA接口中的默认方法 ---- show");}
}//javabean类
public class InterImpl implements InterA{@Overridepublic void method() {System.out.println("实现类重写的抽象方法");}
}//实现类
public class Test {public static void main(String[] args) {//创建实现类的对象InterImpl ii = new InterImpl();ii.method();ii.show();}
}//输出
实现类重写的抽象方法
InterA接口中的默认方法 ---- show
案例二:接口的方法重写
//接口A
public interface InterA {public abstract void method();public default void show(){System.out.println("InterA接口中的默认方法 ---- show");}
}//接口b
public interface InterB {public default void show(){System.out.println("InterB接口中的默认方法 ---- show");}
}//javabean类
public class InterImpl implements InterA{@Overridepublic void method() {System.out.println("实现类重写的抽象方法");}//重写的时候去掉default关键字@Overridepublic void show() {System.out.println("重写接口中的默认方法");}
}//实现:测试
public class Test {public static void main(String[] args) {/*接口中默认方法的定义格式:格式:public default 返回值类型 方法名(参数列表) { }接口中默认方法的注意事项:1.默认方法不是抽象方法,所以不强制被重写。但是如果被重写,重写的时候去掉default关键字2.public可以省略,default不能省略3.如果实现了多个接口,多个接口中存在相同名字的默认方法,子类就必须对该方法进行重写*///创建实现类的对象InterImpl ii = new InterImpl();ii.method();ii.show();}
}//输出
实现类重写的抽象方法
重写接口中的默认方法
6.6.2 新增的静态方法
允许在接口中定义静态方法,需要使用关键字static修饰
接口中静态方法的定义格式:
格式: public static 返回值类型 方法名(参数列表){}范例: public static void show(){ }
- 接口中静态方法的注意事项:
- 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
- public可以省略,static不能省略
案例
//接口
public interface Inter {public abstract void method();public static void show(){System.out.println("Inter接口中的静态方法");}
}//javabean类
public class InterImpl implements Inter{@Overridepublic void method() {System.out.println("InterImpl重写的抽象方法");}//不叫重写public static void show() {System.out.println("InterImpl重写的抽象方法");}}public class Test {public static void main(String[] args) {//调用接口中的静态方法Inter.show();//调用实现类中的静态方法InterImpl.show();//子类把从父类继承下来的虚方法表里面的方法进行覆盖了,这才叫重写。}
}//输出
Inter接口中的静态方法
InterImpl重写的抽象方法
6.6.3 JDK9以后新增加的方法
public class Test {public static void main(String[] args) {/* 接口中私有方法的定义格式:格式1:private 返回值类型 方法名(参数列表) { }范例1:private void show() { }格式2:private static 返回值类型 方法名(参数列表) { }范例2:private static void method() { }
*/}
}
public interface InterA {public static void show1(){System.out.println("show1方法开始执行了");show4();}public static void show2(){System.out.println("show2方法开始执行了");show4();}//普通的私有方法,给默认方法服务的private void show3(){System.out.println("记录程序在运行过程中的各种细节,这里有100行代码");}//静态的私有方法,给静态方法服务的private static void show4(){System.out.println("记录程序在运行过程中的各种细节,这里有100行代码");}}
6.7 接口的应用
1.接口代表规则,是行为的抽象。想要让哪个类拥有一个行为,就让这个类实现对应的接口就可以了。
2.当一个方法的参数是接口时,可以传递接口所有实现类的对象,这种方式称之为接口多态。
6.8适配器设计模式
- 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
- 简单理解:设计模式就是各种套路。
- 适配器设计模式:解决接口与接口实现类之间的矛盾问题
1.当一个接口中抽象方法过多,但是我只要使用其中一部分的时候,就可以适配器设计模式
2.书写步骤:
- 编写中间类XXXAdapter,实现对应的接口
- 对接口中的抽象方法进行空实现
- 让真正的实现类继承中间类,并重写需要用的方法
- 为了避免其他类创建适配器类的对象,中间的适配器类用abstract进行修饰
//接口
public interface Inter {public abstract void method1();public abstract void method2();public abstract void method3();public abstract void method4();public abstract void method5();public abstract void method6();public abstract void method7();public abstract void method8();public abstract void method9();public abstract void method10();
}
//中间类
public abstract class InterAdapter implements Inter{@Overridepublic void method1() {}@Overridepublic void method2() {}@Overridepublic void method3() {}@Overridepublic void method4() {}@Overridepublic void method5() {}@Overridepublic void method6() {}@Overridepublic void method7() {}@Overridepublic void method8() {}@Overridepublic void method9() {}@Overridepublic void method10() {}
}
实现类
public class InterImpl extends InterAdapter{//我需要用到那个方法,就重写哪个方法就可以了@Overridepublic void method5() {System.out.println("只要用第五个方法");}
}
第七章 内部类
**类的五大成员:**属性、方法、构造方法、代码块、内部类
7.1 概述
public class Car {String carName;int carAge;String carColor;public void show(Car this){//是打印调用者车的名字:宾利System.out.println(this.carName);//调用内部类Engine e = new Engine();System.out.println(e.engineName);}//内部类class Engine{String engineName;int engineAge;public void show(){System.out.println(engineName);System.out.println(carName);}}
}
7.2 内部类的分类
按定义的位置来分
- 成员内部类,类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类)
- 静态内部类,类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类)
- 局部内部类,类定义在方法内
- 匿名内部类,没有名字的内部类,可以在方法中,也可以在类中方法外。 (掌握)
7.3 成员内部类
1.成员内部类的代码如何书写
2.如何创建成员内部类的对象
3.成员内部类如何获取外部类的成员变量
成员内部类:
写在成员位置的,属于外部类的成员。
成员内部类可以被一些修饰符所修饰,比如: private,默认,protected,public,static等在成员内部类里面,
JDK16之前不能定义静态变量,JDK 16开始才可以定义静态变量。
public class car {外部类string carName;int carAge;int carcolor;//成员内部类class Engine{string engineName;int engineAge;} }
成员内部类特点:
- 无static修饰的内部类,属于外部类对象的。
- 宿主:外部类对象。
内部类的使用格式:
外部类.内部类。 // 访问内部类的类型都是用 外部类.内部类
获取成员内部类对象的两种方式:
方式一:外部直接创建成员内部类的对象
外部类.内部类 变量 = new 外部类().new 内部类();
方式二:在外部类中定义一个方法提供内部类的对象
方式一:
public class Test {public static void main(String[] args) {// 宿主:外部类对象。// Outer out = new Outer();// 创建内部类对象。Outer.Inner oi = new Outer().new Inner();oi.method();}
}class Outer {// 成员内部类,属于外部类对象的。// 拓展:成员内部类不能定义静态成员。public class Inner{// 这里面的东西与类是完全一样的。public void method(){System.out.println("内部类中的方法被调用了");}}
}方式二:
public class Outer {String name;private class Inner{static int a = 10;}public Inner getInstance(){return new Inner();}
}public class Test {public static void main(String[] args) {Outer o = new Outer();System.out.println(o.getInstance());}
}
成员内部类的细节
编写成员内部类的注意点:
- 成员内部类可以被一些修饰符所修饰,比如: private,默认,protected,public,static等
- 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。
- 创建内部类对象时,对象中有一个隐含的Outer.this记录外部类对象的地址值。(请参见3.6节的内存图)
详解:
内部类被private修饰,外界无法直接获取内部类的对象,只能通过3.3节中的方式二获取内部类的对象
被其他权限修饰符修饰的内部类一般用3.3节中的方式一直接获取内部类的对象
内部类被static修饰是成员内部类中的特殊情况,叫做静态内部类下面单独学习。
内部类如果想要访问外部类的成员变量,外部类的变量必须用final修饰,JDK8以前必须手动写final,JDK8之后不需要手动写,JDK默认加上
7.4 成员内部类面试题
请在?地方向上相应代码,以达到输出的内容
注意:内部类访问外部类对象的格式是:外部类名.this
public class Test {public static void main(String[] args) {Outer.inner oi = new Outer().new inner();oi.method();}
}class Outer { // 外部类private int a = 30;// 在成员位置定义一个类class inner {private int a = 20;public void method() {int a = 10;System.out.println(???); // 10 答案:aSystem.out.println(???); // 20 答案:this.aSystem.out.println(???); // 30 答案:Outer.this.a}}
}
7.5 静态内部类
静态内部类特点:
静态内部类是一种特殊的成员内部类。
有static修饰,属于外部类本身的。
总结:静态内部类与其他类的用法完全一样。只是访问的时候需要加上外部类.内部类。
拓展1:静态内部类可以直接访问外部类的静态成员。
拓展2:静态内部类不可以直接访问外部类的非静态成员,如果要访问需要创建外部类的对象。
拓展3:静态内部类中没有银行的Outer.this。
内部类的使用格式:
外部类.内部类。
静态内部类对象的创建格式:
外部类.内部类 变量 = new 外部类.内部类构造器;
调用方法的格式:
- 调用非静态方法的格式:先创建对象,用对象调用
- 调用静态方法的格式:外部类名.内部类名.方法名();
案例演示:
// 外部类:Outer01
class Outer01{private static String sc_name = "黑马程序";// 内部类: Inner01public static class Inner01{// 这里面的东西与类是完全一样的。private String name;public Inner01(String name) {this.name = name;}public void showName(){System.out.println(this.name);// 拓展:静态内部类可以直接访问外部类的静态成员。System.out.println(sc_name);}}
}public class InnerClassDemo01 {public static void main(String[] args) {// 创建静态内部类对象。// 外部类.内部类 变量 = new 外部类.内部类构造器;Outer01.Inner01 in = new Outer01.Inner01("张三");in.showName();}
}
7.6 局部内部类
- 局部内部类 :定义在方法中的类。
局部内部类1.将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。2.外界是无法直接使用局部内部类,需要在方法内部创建对象并使用。3.该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
定义格式:
class 外部类名 {数据类型 变量名;修饰符 返回值类型 方法名(参数列表) {// …class 内部类 {// 成员变量// 成员方法}}
}
public class Outer {int b = 20;public void show(){int a = 10;//局部内部类class Inner{String name;int age;public void method1(){System.out.println(a);System.out.println(b);System.out.println("局部内部类中的method1方法");}public static void method2(){System.out.println("局部内部类中的method2静态方法");}}//创建局部内部类的对象Inner i = new Inner();System.out.println(i.name);System.out.println(i.age);i.method1();Inner.method2();}
}
public class Test {public static void main(String[] args) {/*局部内部类1.将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量。2.外界是无法直接使用局部内部类,需要在方法内部创建对象并使用。3.该类可以直接访问外部类的成员,也可以访问方法内的局部变量。*///调用show方法,让代码执行Outer o = new Outer();o.show();}
}
7.7 匿名内部类
1.什么是匿名内部类?
隐藏了名字的内部类,可以写在成员位置,也可以写在局部位置。
2.格式的细节
包含了继承或实现,方法重写,创建对象。
整体就是一个类的子类对象或者接口的实现类对象
3.使用场景
当方法的参数是接口或者类时,
以接口为例,可以传递这个接口的实现类对象,
如果实现类只要使用一次,就可以用匿名内部类简化代码。
案例
//接口
public interface Swim {public abstract void swimming();
}
//实现1
public class Demo07 {public static void main(String[] args) {new Swim() {@Overridepublic void swimming() {System.out.println("自由泳...");}}.swimming();}
}//输出
自由泳...
//实现2
public class Demo07 {public static void main(String[] args) {// 接口 变量 = new 实现类(); // 多态,走子类的重写方法Swim s2 = new Swim() {@Overridepublic void swimming() {System.out.println("蛙泳...");}};s2.swimming();}
}//输出
蛙泳...
案例2
interface Swim {public abstract void swimming();
}public class Demo07 {public static void main(String[] args) {// 普通方式传入对象// 创建实现类对象Student s = new Student();goSwimming(s);// 匿名内部类使用场景:作为方法参数传递Swim s3 = new Swim() {@Overridepublic void swimming() {System.out.println("蝶泳...");}};// 传入匿名内部类goSwimming(s3);// 完美方案: 一步到位goSwimming(new Swim() {public void swimming() {System.out.println("大学生, 蛙泳...");}});goSwimming(new Swim() {public void swimming() {System.out.println("小学生, 自由泳...");}});}// 定义一个方法,模拟请一些人去游泳public static void goSwimming(Swim s) {s.swimming();}
}
7.面向对象进阶(1)相关推荐
- Python之面向对象进阶
Python之面向对象进阶 进阶有:Python 类的成员.成员修饰符.类的特殊成员. 一.类的成员 类的成员可以分为三大类:字段.方法和属性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据 ...
- Day 23 面向对象进阶
目录 面向对象进阶 类的继承 什么是继承 为什么要用继承 对象的继承 对象查找属性的顺序 类的派生 类的组合 菱形继承问题 类的分类 菱形继承问题 多态与多态性 多态 多态性 面向对象进阶 类的继承 ...
- Java面向对象进阶
相关额外的代码待上传... /*** 面向对象进阶*/ package com.org.lxh;import com.org.lxh.ext.Demo; import com.org.lxh.impl ...
- JavaSE——面向对象进阶(封装、this、static、代码块、包、权限修饰符、main方法详解)
第2节 面向对象进阶 一.封装与private 概述: 封装的意义在于保护或者防止代码(数据)被我们无意中破坏.保护成员属性,不让类以外的程序直接访问和修改. 封装原则: 隐藏对象的属性和实现细节,仅 ...
- python内置函数面向对象_Pyhton——面向对象进阶二:类的内置函数补充、描述符...
Pyhton--面向对象进阶二: 一.类的内置函数补充 1.isinstance(obj,cls)--检查obj是否是该类的对象 class Hoo: def __init__(self,name,t ...
- 第四十三篇 面向对象进阶2
目录 第四十三篇 面向对象进阶2 一.类的封装 1.封装分为两个层面 2.应用 二.类的property特性 1. BMI(Body Mass Index):身体体质指数 2.装饰器用法(只在Pyth ...
- Python面向对象进阶和socket网络编程
写在前面 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese:def __init__(self, ...
- Java大数据-Week2-Day2面向对象进阶
第二章第三节 面向对象进阶 文章目录 第二章第三节 面向对象进阶 前言 封装 this关键字 静态static 包 包2 权限修饰符 代码块 main方法详解 总结 前言 # 第三章第3节 面向对象进 ...
- python进阶课程目标 学习内容_Python学习教程(Python学习路线):第九天-面向对象进阶...
面向对象进阶 在前面的章节我们已经了解了面向对象的入门知识,知道了如何定义类,如何创建对象以及如何给对象发消息.为了能够更好的使用面向对象编程思想进行程序开发,我们还需要对Python中的面向对象编程 ...
- Java进阶(一)面向对象进阶简介
一.面向对象进阶简介 面向对象知识的学习建议: 多关注语法点的基本作用. 多进行思考和记忆.练习. 要自信,不要在短期想能做什么. 面向对象进阶课程:需要学习哪些语法? static关键字:定义的成员 ...
最新文章
- 顺序表的删除(按位置删、头删、尾删)
- python 地址模糊匹配_使用python处理selenium中的xpath定位元素的模糊匹配问题
- 笔记本的处理器型号怎么区别好坏
- Android:Activity(页面)的生存周期
- C#中string类型赋值问题
- Hibernate - DetachedCriteria 的完整用法
- (转-这篇文章非常棒) Thread的中断机制(interrupt)
- DW 在onload运行recordset find.html时 发生了以下javascript错误
- 用DotNetOpenAuth实现基于OAuth 2.0的web api授权 (一)Getting Start
- python对象转为字符串
- 2021最新一线互联网大厂常见高并发面试题解析,快手Java面试算法题
- c语言坐标三角形判断,C语言输入三角形边长判断其类型并输出面积实例代码
- 在Mac上使用中国银行和工商银行网银
- python免费的实时语音交互(讯飞语音识别+青云客Robot)
- 更改电脑用户名(C:\Users\用户名)
- 链路聚合+MSTP实验
- 中华英才网全年亏损1.75亿 招聘行业不行了?
- Idea导包自动去除Import xxx.*里的星号
- TCL雷鸟电视卸载内置应用
- 【计量经济学】简单回归模型
热门文章
- hdmi怎么支持2k分辨率_选择2K显示器有没有必要?
- zto中通电子面单cpcl打印指令实例
- 使用Aircrack-ng工具破解WEP、WPA/WPA2加密的无线网络
- python基于PHP+MySQL的在线音乐点歌系统
- 宏碁笔记本关闭安全启动Secure Boot,就是改为Disabled
- 曹祖圣VB.NET视频学习工具
- 深圳社保明细查询, 深圳社保参保证明
- 13.创建活动、布局、活动关联布局、注册活动
- Android学习笔记——活动,从创建到销毁
- 计算机固态和机械什么意思,固态硬盘和机械硬盘有什么不同?详解固态硬盘和机械硬盘...