文章目录

  • 一、复习
    • 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 封装的步骤实现

  1. private修饰成员变量
public class Student {private String name;private int age;
}
  1. 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 继承的特点

  1. Java只支持单继承,不支持多继承。
// 一个类只能有一个父类,不可以有多个父类。
class A {}
class B {}
class C1 extends A {} // ok
// class C2 extends A, B {} // error
  1. 一个类可以有多个子类。
// A可以有多个子类
class A {}
class C1 extends A {}
class C2 extends  A {}
  1. 可以多层继承。
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报错之后,知道如何修改即可。

关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。

  2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。

    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。

  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。

  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。

    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

  5. 抽象类存在的意义是为了被子类继承。

    理解:抽象类中已经实现的是模板中确定的成员,抽象类不确定如何实现的定义成抽象方法,交给具体的子类去实现。

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开始接口中新增的方法

  1. JDK7以前:接口中只能定义抽象方法。
  2. JDK8:接口中可以定义有方法体的方法。(默认、静态)
  3. JDK9:接口中可以定义私有方法。
  4. 私有方法分为两种:普通的私有方法,静态的私有方法

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 内部类的分类

按定义的位置来分

  1. 成员内部类,类定义在了成员位置 (类中方法外称为成员位置,无static修饰的内部类)
  2. 静态内部类,类定义在了成员位置 (类中方法外称为成员位置,有static修饰的内部类)
  3. 局部内部类,类定义在方法内
  4. 匿名内部类,没有名字的内部类,可以在方法中,也可以在类中方法外。 (掌握)

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());}
}

成员内部类的细节

编写成员内部类的注意点:

  1. 成员内部类可以被一些修饰符所修饰,比如: private,默认,protected,public,static等
  2. 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。
  3. 创建内部类对象时,对象中有一个隐含的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)相关推荐

  1. Python之面向对象进阶

    Python之面向对象进阶 进阶有:Python 类的成员.成员修饰符.类的特殊成员. 一.类的成员 类的成员可以分为三大类:字段.方法和属性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据 ...

  2. Day 23 面向对象进阶

    目录 面向对象进阶 类的继承 什么是继承 为什么要用继承 对象的继承 对象查找属性的顺序 类的派生 类的组合 菱形继承问题 类的分类 菱形继承问题 多态与多态性 多态 多态性 面向对象进阶 类的继承 ...

  3. Java面向对象进阶

    相关额外的代码待上传... /*** 面向对象进阶*/ package com.org.lxh;import com.org.lxh.ext.Demo; import com.org.lxh.impl ...

  4. JavaSE——面向对象进阶(封装、this、static、代码块、包、权限修饰符、main方法详解)

    第2节 面向对象进阶 一.封装与private 概述: 封装的意义在于保护或者防止代码(数据)被我们无意中破坏.保护成员属性,不让类以外的程序直接访问和修改. 封装原则: 隐藏对象的属性和实现细节,仅 ...

  5. python内置函数面向对象_Pyhton——面向对象进阶二:类的内置函数补充、描述符...

    Pyhton--面向对象进阶二: 一.类的内置函数补充 1.isinstance(obj,cls)--检查obj是否是该类的对象 class Hoo: def __init__(self,name,t ...

  6. 第四十三篇 面向对象进阶2

    目录 第四十三篇 面向对象进阶2 一.类的封装 1.封装分为两个层面 2.应用 二.类的property特性 1. BMI(Body Mass Index):身体体质指数 2.装饰器用法(只在Pyth ...

  7. Python面向对象进阶和socket网络编程

    写在前面 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese:def __init__(self, ...

  8. Java大数据-Week2-Day2面向对象进阶

    第二章第三节 面向对象进阶 文章目录 第二章第三节 面向对象进阶 前言 封装 this关键字 静态static 包 包2 权限修饰符 代码块 main方法详解 总结 前言 # 第三章第3节 面向对象进 ...

  9. python进阶课程目标 学习内容_Python学习教程(Python学习路线):第九天-面向对象进阶...

    面向对象进阶 在前面的章节我们已经了解了面向对象的入门知识,知道了如何定义类,如何创建对象以及如何给对象发消息.为了能够更好的使用面向对象编程思想进行程序开发,我们还需要对Python中的面向对象编程 ...

  10. Java进阶(一)面向对象进阶简介

    一.面向对象进阶简介 面向对象知识的学习建议: 多关注语法点的基本作用. 多进行思考和记忆.练习. 要自信,不要在短期想能做什么. 面向对象进阶课程:需要学习哪些语法? static关键字:定义的成员 ...

最新文章

  1. 顺序表的删除(按位置删、头删、尾删)
  2. python 地址模糊匹配_使用python处理selenium中的xpath定位元素的模糊匹配问题
  3. 笔记本的处理器型号怎么区别好坏
  4. Android:Activity(页面)的生存周期
  5. C#中string类型赋值问题
  6. Hibernate - DetachedCriteria 的完整用法
  7. (转-这篇文章非常棒) Thread的中断机制(interrupt)
  8. DW 在onload运行recordset find.html时 发生了以下javascript错误
  9. 用DotNetOpenAuth实现基于OAuth 2.0的web api授权 (一)Getting Start
  10. python对象转为字符串
  11. 2021最新一线互联网大厂常见高并发面试题解析,快手Java面试算法题
  12. c语言坐标三角形判断,C语言输入三角形边长判断其类型并输出面积实例代码
  13. 在Mac上使用中国银行和工商银行网银
  14. python免费的实时语音交互(讯飞语音识别+青云客Robot)
  15. 更改电脑用户名(C:\Users\用户名)
  16. 链路聚合+MSTP实验
  17. 中华英才网全年亏损1.75亿 招聘行业不行了?
  18. Idea导包自动去除Import xxx.*里的星号
  19. TCL雷鸟电视卸载内置应用
  20. 【计量经济学】简单回归模型

热门文章

  1. hdmi怎么支持2k分辨率_选择2K显示器有没有必要?
  2. zto中通电子面单cpcl打印指令实例
  3. 使用Aircrack-ng工具破解WEP、WPA/WPA2加密的无线网络
  4. python基于PHP+MySQL的在线音乐点歌系统
  5. 宏碁笔记本关闭安全启动Secure Boot,就是改为Disabled
  6. 曹祖圣VB.NET视频学习工具
  7. 深圳社保明细查询, 深圳社保参保证明
  8. 13.创建活动、布局、活动关联布局、注册活动
  9. Android学习笔记——活动,从创建到销毁
  10. 计算机固态和机械什么意思,固态硬盘和机械硬盘有什么不同?详解固态硬盘和机械硬盘...