09_多态_代码块_内部类

IT公司有多名员工,按照员工负责的工作不同,进行了部门的划分(研发部、维护部)。
研发部(Developer)根据所需研发的内容不同,又分为 JavaEE工程师 、Android工程师 ;
维护部(Maintainer)根据所需维护的内容不同,又分为 网络维护工程师(Network) 、硬件维护工程师(Hardware) 。

公司的每名员工都有他们自己的员工编号、姓名,并要做他们所负责的工作。

工作内容:
- JavaEE工程师: 员工号为xxx的 xxx员工,正在研发电商网站
- Android工程师:员工号为xxx的 xxx员工,正在研发电商的手机客户端软件
- 网络维护工程师:员工号为xxx的 xxx员工,正在检查网络是否畅通
- 硬件维护工程师:员工号为xxx的 xxx员工,正在修复电脑主板

请根据描述,完成员工体系中所有类的定义,并指定类之间的继承关系。进行XX工程师类的对象创建,完成工作方法的调用。
public abstract class Employee {
    private int id;
    private String name;

    public Employee() {
    }

    public Employee(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public abstract void work();
}
====================================================
public abstract class Developer extends Employee{
}
====================================================
public class JavaEE extends Developer{
    @Override
    public void work() {
        System.out.println("员工号为:"+this.getId()+"的"+this.getName()+"正在开发网站...");
    }
}
====================================================
public class Test01 {
    public static void main(String[] args) {
        JavaEE javaEE = new JavaEE();
        javaEE.setId(1);
        javaEE.setName("张三");
        javaEE.work();
    }
}
    

1.封装:将细节隐藏起来(不让外界直接使用),对外提供一套公共的接口(让外界通过这个公共接口间接调用隐藏起来的细节)

​ a.有代表性的关键字:private -> 私有化

​ b.get/set方法 -> 提供的公共接口

​ c.构造:

​ 无参构造:new对象

​ 有参构造:new对象的同时,为属性赋值

2.继承:将子类中共有的内容抽取到父类中,子类直接继承父类,就可以直接使用父类中非私有成员

a.关键字:extends

b.成员变量:看等号左边是谁

​ 成员方法:看new的是谁

3.抽象:定义抽象类,里面定义抽象方法

a.定义子类,继承抽象父类

b.重写所有抽象方法

c.创建子类对象,调用重写的方法

第一章.多态

1.面向对象三大特征: 封装   继承   多态

1.多态的介绍

1.怎么学多态:不要从字面上来学
  a.学多态的前提
  b.怎么写代码就是多态了
  c.用多态有啥好处
2.多态前提 :
  a.必须有子父类继承关系或者接口实现关系
  b.必须有方法的重写(没有方法的重写,多态没有任何意义)
  c.创建对象时:父类引用指向子类对象
    Fu fu = new Zi() -> 大类型接收小类型数据  

2.多态的基本使用

public abstract class Animal {
    public abstract void eat();
}
public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

    /**
     * 子类特有功能
     */
    public void watchHouse() {
        System.out.println("狗看家");
    }
}

public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    /**
     * 子类特有功能
     */
    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}
public class Test01 {
    public static void main(String[] args) {
        //原始方式创建对象
        Dog dog = new Dog();
        dog.eat();
        dog.watchHouse();

        Cat cat = new Cat();
        cat.eat();
        cat.catchMouse();

        System.out.println("======================");

        //多态方式创建对象
        Animal animal1 = new Dog();
        animal1.eat();
        //animal1.watchHouse(); //编译错误,父类引用不能调用子类特有方法
    }
}
public interface USB {
    void open();
    void close();
}
public class Mouse implements USB {
    @Override
    public void open() {
        System.out.println("鼠标打开了");
    }

    @Override
    public void close() {
        System.out.println("鼠标关闭了");
    }

    //特有方法
    public void click() {
        System.out.println("鼠标点击了");
    }
}

public class KeyBorad implements USB {
    @Override
    public void open() {
        System.out.println("键盘打开了");
    }

    @Override
    public void close() {
        System.out.println("键盘关闭了");
    }

    //特有方法
    public void input() {
        System.out.println("键盘打字了");
    }
}
public class Test01 {
    public static void main(String[] args) {
        //接口类型的变量可以指向实现类的对象
        USB u1 = new Mouse();
        //调用方法
        u1.open();
        u1.close();

        USB u2 = new KeyBorad();
        u2.open();
        u2.close();
    }
}

3.多态的条件下成员的访问特点

3.1成员变量

看等号左边是谁,先调用谁中的
public class Fu {
    int num = 10;
}
public class Zi extends Fu {
        int num = 20;
}
public class Test01 {
    public static void main(String[] args) {
        Fu fu = new Zi();
        System.out.println(fu.num); // 10
    }
}

3.2成员方法

看等号右边new的是谁,先调用谁中的方法,子类没有找父类
public class Fu {
    int num = 10;
    public void method(){
        System.out.println("Fu method");
    }
}
public class Zi extends Fu {
    int num = 20;
    @Override
    public void method(){
        System.out.println("Zi method");
    }
}

public class Test01 {
    public static void main(String[] args) {
        Fu fu = new Zi();
        System.out.println(fu.num); // 10
        fu.method(); // Zi method
    }
}

4.多态的好处(为什么学多态)

多态有一个弊端:不能直接调用子类特有功能

1.原始方式:
  a.优点:既能调用父类继承的,还能调用重写的,还能调用子类特有的
  b.缺点:扩展性差
      
2.多态方式:
  a.优点:扩展性强
  b.缺点:不能直接调用子类特有功能
public abstract class Animal {
    public abstract void eat();
}

public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗啃骨头");
    }
}
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
public class Test01 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        method(dog);

        System.out.println("=======================");
        Cat cat = new Cat();
        method(cat);

        System.out.println("=======================");

   /*     Pig pig = new Pig();
        method(pig);

        System.out.println("=======================");

        Duck duck = new Duck();
        method(duck);*/
    }

    public static void method(Dog dog) {
        dog.eat();
    }

    public static void method(Cat cat) {
        cat.eat();
    }
}
public class Test02 {
    public static void main(String[] args) {
        /*
           好比是:
             int i = 10;
             double b = i;

             float f = 2.5F;

             b = f;
         */
/*        Animal animal = new Dog();
        animal.eat();
        animal = new Cat();
        animal.eat();*/
        Dog dog = new Dog();
        method(dog);

        System.out.println("================");

        Cat cat = new Cat();
        method(cat);
    }

    /**
     * 传递Dog对象的时候->参数位置 -> Animal animal = dog
     * 传递Cat对象的时候->参数位置 -> Animal animal = cat
     * 
     * 形参位置传递的是父类类型,那么就可以接收任意它的子类对象
     * 传递哪个子类对象,就指向哪个子类对象,就会动态调用哪个
     * 子类对象重写的方法 -> 扩展性强
     * @param animal
     */
    public static void method(Animal animal){
        animal.eat();
    }
}

5.多态中的转型

5.1向上转型_自动类型转换

父类引用指向子类对象 -> 多态默认的形式

5.2向下转型_强转

1.将父类类型强转成子类类型
  Fu fu = new Zi()
  Zi zi = (Zi)fu;  -> 向下转型
  
  好比是:
  double b = 10;
  int i = (int)b;

2.作用:可以调用子类特有功能了

6.转型可能会出现的问题

1.问题:ClassCastException -> 类型转换异常
2.出现的原因: 等号左右两边类型不一致,转型之后就会出现类型转换异常
3.解决:强转之前,判断类型
  a.对象名 instanceof 类型 -> 判断关键字前面的对象是否属于关键字后面的类型
  b.判断类型新特性:
    对象名 instanceof 类型 对象名2 -> 隐含强转步骤
public class Test03 {
    public static void main(String[] args) {

        Dog dog = new Dog();
        method(dog);

        System.out.println("================");

        Cat cat = new Cat();
        method(cat);
    }

    /**
     * Animal animal = dog
     * Animal animal = cat
     * @param animal
     */
    public static void method(Animal animal){
        animal.eat();
        //向下转型
/*        if (animal instanceof Dog){
            Dog dog = (Dog) animal;
            dog.lookHome();
        }
        if (animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.catchMouse();
        }*/

        if (animal instanceof Dog dog){
            dog.lookHome();
        }
        if (animal instanceof Cat cat){
            cat.catchMouse();
        }

    }
}

第二章.代码块

1.1构造代码块

1.格式:
  {
    代码   
  }
2.执行特点:
  优先于构造方法执行,new一次,就执行一次
public class Person {
    public Person(){
        System.out.println("无参构造方法");
    }
    /**
     * 构造代码块
     */
    {
        System.out.println("构造代码块");
    }
}

public class Test01 {
    public static void main(String[] args) {
        Person person = new Person();
        Person person1 = new Person();
    }
}

1.2静态代码块

1.格式:
  static{
      代码
  }
2.执行特点:
  优先于构造代码块和构造方法执行的,只执行一次
public class Person {
    public Person(){
        System.out.println("无参构造方法");
    }
    /**
     * 构造代码块
     */
    {
        System.out.println("构造代码块");
    }

    /**
     * 静态代码块
     */
    static{
        System.out.println("静态代码块");
    }
}
public class Test01 {
    public static void main(String[] args) {
        Person person = new Person();
        Person person1 = new Person();
    }
}

1.3.静态代码块使用场景

如果一些数据需要最先初始化,而且是需要初始化一次,我们就可以将这些数据放到静态代码块中

第三章.内部类

1.什么时候使用内部类:
  当一个事物的内部,还有一个部分需要完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类
  比如:人类都有心脏,人类本身需要用属性,行为去描述,那么人类内部的心脏也需要心脏特殊的属性和行为来描述,此时心脏就可以定义成内部类,人类中的一个内部类
  
  当一个类内部的成员也需要用属性和行为描述时,就可以定义成内部类了
      
2.在java中允许一个类的定义位于另外一个类内部,前者就称之为内部类,后者称之为外部类
  class A{
      class B{
          
      }
  }
  A就是B的外部类
  B就是A的内部类
      
3.分类:
  成员内部类(静态,非静态)
  局部内部类->  匿名内部类(重点) -> 匿名内部类属于局部内部类一种
 

1 静态成员内部类

1.格式:直接在定义内部类的时候加上static关键字即可
  public class A{
      static class B{
          
      }
  }

2.注意:
  a.内部类中可以定义属性,方法,构造等
  b.静态内部类可以被final或者abstract修饰
    给final修饰,不能被继承
    被abstract修饰,不能new
  c.静态内部类不能调用外部的非静态成员
  d.内部类还可以被四种权限修饰符修饰
 
3.调用静态内部类成员:
  外部类.内部类 对象名 = new 外部类.内部类()
public class Person {
    public void eat(){
        System.out.println("吃吃吃");
        //new Heart().jump();
    }
    /**
     * 静态成员内部类
     */
    static class Heart{
        public void jump(){
            System.out.println("心脏跳动");
        }
    }
}

public class Test01 {
    public static void main(String[] args) {
       Person.Heart heart = new Person.Heart();
       heart.jump();
    }
}

2 非静态成员内部类

1.格式:
  public class 类名{
      class 类名{
          
      }
  }

2.注意:
  a.内部类中可以定义属性,方法,构造等
  b.静态内部类可以被final或者abstract修饰
    给final修饰,不能被继承
    被abstract修饰,不能new
  c.静态内部类不能调用外部的非静态成员
  d.内部类还可以被四种权限修饰符修饰
      
3.调用非静态成员内部类
  外部类.内部类 对象名 = new 外部类().new 内部类()
public class Person {
    public void eat(){
        System.out.println("吃吃吃");
        //new Heart().jump();
    }
    /**
     * 非静态成员内部类
     */
    class Heart{
        public void jump(){
            System.out.println("心脏跳动");
        }
    }
}

public class Test01 {
    public static void main(String[] args) {
       Person.Heart heart = new Person().new Heart();
       heart.jump();
    }
}

外部类成员变量,内部类成员变量,内部类局部变量,这三种变量重名时,如何访问

public class Student {
    String name = "张三";

    class InnerClass{
        String name = "李四";
        public void study(){
            String name = "王五";
            System.out.println(name);//王五
            System.out.println(this.name);//李四
            System.out.println(Student.this.name);//张三
        }
    }
}
public class Test02 {
    public static void main(String[] args) {
        Student.InnerClass innerClass = new Student().new InnerClass();
        innerClass.study();
    }
}

3.局部内部类

3.1.局部内部类基本操作

1.可以定义在方法中,代码块中,构造方法中
public class Person {
    public void eat(){
        //局部内部类
        class Heart{
            public void jump(){
                System.out.println("心脏跳动");
            }
        }

        Heart heart = new Heart();
        heart.jump();
    }
}

public class Test01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.eat();
    }
}

3.2.局部内部类实际操作

3.2.1.接口类型作为方法参数传递和返回

1.接口作为方法参数传递,我们实参需要传递实现类对象

2.接口作为方法返回值返回,我们应该实际返回实现类对象

public interface USB {
    void open();
}

public class Mouse implements USB{
    @Override
    public void open() {
        System.out.println("鼠标开启");
    }
}

public class Test01 {
    public static void main(String[] args) {
        Mouse mouse = new Mouse();
        method(mouse);

        System.out.println("================");
        USB usb = method01();//USB usb = mouse
        usb.open();
    }

    /**
     * 接口作为方法参数传递
     * 实参传递实现类对象
     */
    public static void method(USB usb){//USB usb = mouse
        usb.open();
    }

    /**
     * 接口作为方法返回值返回
     * 返回的是实现类对象
     */
    public static USB method01(){
        Mouse mouse = new Mouse();
        return mouse;
    }
}
3.2.2.抽象类作为方法参数和返回值

1.抽象类作为方法参数传递,传递的是子类对象

2.抽象类作为方法返回值返回,返回的是子类对象

public abstract class Animal {
    public abstract void eat();
}
public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃屎");
    }
}
public class Test01 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        method(dog);

        System.out.println("=======================");

        Animal animal = method01();//Animal animal = dog
        animal.eat();
    }

    /**
     * 抽象类作为方法参数传递
     * 传递的是子类对象
     * @param animal
     */
    public static void method(Animal animal){//Animal animal = dog
        animal.eat();
    }

    /**
     * 抽象类作为方法返回值返回
     */
    public static Animal method01(){
        Dog dog = new Dog();
        return dog;
    }
}
3.2.3.普通类做方法参数和返回值

1.普通类作为方法参数传递,传递的是对象

2.普通类作为方法返回值返回,应该返回对象

public class Person {
    public void eat(){
        System.out.println("吃吃吃");
    }
}
public class Test01 {
    public static void main(String[] args) {
        Person person = new Person();
        method(person);
        System.out.println("================");
        Person person1 = method01();
        person1.eat();
    }
    /**
     * 普通类作为方法参数传递
     * 传递的是对象
     */
    public static void method(Person person){
        person.eat();
    }

    /**
     * 普通类作为方法的返回值返回
     * 返回的也是对象
     */
    public static Person method01(){
        Person person = new Person();
        return person;
    }
}

2.2.4.局部内部类实际操作
public interface USB {
    void open();
}
public class Test01 {
    public static void main(String[] args) {
        USB usb = method();
        usb.open();
    }
    public static USB method(){
        class Mouse implements USB{
            @Override
            public void open() {
                System.out.println("usb打开了");
            }
        }
        Mouse mouse = new Mouse();
        return mouse;
    }
}

4.局部内部类之匿名内部类

1.描述:
  上面的代码我们明确定义了一个类,作为接口的实现类,这个类叫做Mouse,这种类我们可以跟它叫做"有名的局部内部类",而这个有名的局部内部类作为了接口的实现类使用
      
2.匿名内部类:
  说白了就是没有明确定义出来的"局部内部类",(说白了这个局部内部类我们就没有定义)
 
3.怎么用匿名内部类:
  既然我们没有定义,那我们直接new这个匿名内部类的对象即可
      
4.怎么创建匿名内部类对象:
  a.利用创建匿名对象的方式去创建匿名内部类对象
    new 接口名/抽象类名(){
       重写的抽象方法  
    }.重写的方法();

    好比是: new Mouse().open()
        
  b.利用创建有名对象的方式去创建匿名内部类对象
    接口名/抽象类名 对象名 =  new 接口名/抽象类名(){
       重写的抽象方法  
    };

    对象名.重写的方法();

    好比是: Mouse mouse = new Mouse()
           mouse.open();

5.注意:jvm在执行的时候会根据我们的创建匿名内部类的对象自动生成一个匿名内部类出来
    
6.你们要知道的是:匿名内部类不是我们自己手动定义出来的,我们直接去创建匿名内部类对象,jvm会根据我们创建的对象自动编译出一个匿名内部类来    
public interface USB {
    void open();
}
public class Test02 {
    public static void main(String[] args) {
        /*
            a.利用创建匿名对象的方式去创建匿名内部类对象
              new 接口名/抽象类名(){
                 重写的抽象方法
              }.重写的方法();

              好比是: new Mouse().open()
         */
        new USB(){
            @Override
            public void open() {
                System.out.println("usb打开了");
            }
        }.open();

        System.out.println("=========================");

        /*
           b.利用创建有名对象的方式去创建匿名内部类对象
             接口名/抽象类名 对象名 =  new 接口名/抽象类名(){
                重写的抽象方法
             };

             对象名.重写的方法();

             好比是: Mouse mouse = new Mouse()
                    mouse.open();
         */
        USB usb = new USB(){

            @Override
            public void open() {
                System.out.println("usb打开了");
            }
        };
        usb.open();
    }
}

4.1.匿名内部类复杂用法_当参数传递

public interface USB {
    public abstract void open();
}
public class Test01 {
    public static void main(String[] args) {
        method(new USB() {
            @Override
            public void open() {
                System.out.println("USB打开");
            }
        });
    }

    public static void method(USB usb){
        usb.open();
    }
}

4.2.匿名内部类复杂用法_当返回值返回

public interface USB {
    public abstract void open();
}

public class Test02 {
    public static void main(String[] args) {
        USB usb = method();
        usb.open();
    }

    public static USB method(){
        return new USB() {
            @Override
            public void open() {
                System.out.println("USB打开");
            }
        };
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值