zoukankan      html  css  js  c++  java
  • 【JAVA基础】08 面向对象3

    1. 多态

    • 多态polymorhic概述

      • 事物存在的多种形态。
    • 多态前提
      • 要有继承关系
      • 要有方法重写
      • 要有父类引用指向子类对象
    • 案例演示
      • 代码体现多态
      • class  Demo1_Polymorphic{
            public static void main(String[] args) {
                Cat c = new Cat();
                c.eat();
        
                Animal a = new Cat(); // 父类引用指向子类对象
                a.eat();  // 输出“猫吃鱼”
            }
        }
        
        
        class Animal {
            public void eat() {
                System.out.println("动物吃饭");
            }
        }
        
        class Cat extends Animal {
            public void eat() {
                System.out.println("猫吃鱼");
            }
        }
    • 多态中的成员访问特点
      • 成员变量
        • 编译看左边(父类),运行看左边(父类)
        • Father f = new Son();
        • class Demo2_Polymorphic {
              public static void main(String[] args) {
                  Father f = new Son();
                  System.out.println(f.num); //输出10
              }
          }
          
          class Father {
              int num = 10;
          
          }
          
          class Son extends Father {
              int num = 20;
          }

           

           如果再上面例子的基础上,再生成一个Son类对象,则

        • class Demo2_Polymorphic {
              public static void main(String[] args) {
                  Father f = new Son();
                  System.out.println(f.num); //输出10
          
                  Son s = new Son();
                  System.out.println(s.num);   //输出20
              }
          }
          
          class Father {
              int num = 10;
          
          }
          
          class Son extends Father {
              int num = 20;
          }

           

      • 成员方法
        • 编译看左边(父类),运行看右边(子类)——又称“动态绑定”
        • Father f = new Son();
        • 编译时,看父类中有没有该成员方法,有则编译成功;运行则动态绑定到子类的成员方法上,运行子类的成员方法。
        • class Demo3_Polymorphic {
              public static void main(String[] args) {
                  Father f = new Son();
                  f.print();// 输出son
              }
          }
          
          class Father {
              int num = 10;
          
              public void print() {
                  System.out.println("father");
              }
          
          }
          
          class Son extends Father {
              int num = 20;
          
              public void print() {
                  System.out.println("son");
              }
          }

           

      • 静态方法
        • 编译看左边(父类),运行看左边(父类)
        • 静态和类相关,算不上重写,所以,访问还是左边的
        • class Demo4_Polymorphic {
              public static void main(String[] args) {
                  Father f = new Son();
                  f.method();  //输出"father static method";
                  // 相当于是Father.method(); 调用父类的方法
              }
          }
          
          class Father {
              int num = 10;
          
              public void print() {
                  System.out.println("father");
              }
          
              public static void method(){
                  System.out.println("father static method");
              }
          
          }
          
          class Son extends Father {
              int num = 20;
          
              public void print() {
                  System.out.println("son");
              }
          
              public static void method(){
                  System.out.println("son static method");
              }
          }
      • 总结:
        • 只有非静态的成员方法,编译看左边(父类),运行看右边(子类)
        • 其他都是编译看左边(父类),运行看左边(父类)
    • 案例:超人的故事
      • 通过该案例帮助理解多态的现象。
      • class Demo5_Polymorphic {
            public static void main(String[] args) {
                Person p = new SuperMan(); // 父类引用指向子类对象,超人提升为人
        
                System.out.println(p.name);// 输出“John”
                p.谈生意();  // 输出"谈几个亿的大单子"
                
                
                //p.fly();  //编译出错
                
            }
        }
        
        class Person {
            String name = "John";
        
            public void 谈生意() {
                System.out.println("谈生意");
            }
        }
        
        class SuperMan extends Person {
            String name = "Super man";
        
            public void 谈生意() {
                System.out.println("谈几个亿的大单子");
            }
        
            public void fly() {
                System.out.println("飞出去救人");
            }
        }
        View Code

    超人作为人类身份的属性信息对外展示,Person类和SuperMan类中重写的方法,实际执行的是超人身份的方法;

    在这个例子中,父类中没有fly方法,故编译失败,也无法执行。针对这个,要考虑下面的 向上转型和向下转型 的问题。
    • 多态中 向上转型和向下转型
      • 向上转型
        • Person p = new SuperMan();
        • 父类引用指向子类对象,就是向上转型
      • 向下转型
        • SuperMan sm = (SuperMan)p;
        • class Demo5_Polymorphic {
              public static void main(String[] args) {
                  Person p = new SuperMan(); // 父类引用指向子类对象,超人提升为人
          
                  System.out.println(p.name);// 输出“John”
                  p.谈生意();  // 输出"谈几个亿的大单子"
                  
                  
                  //p.fly();  //编译出错
          
                  SuperMan sm = (SuperMan)p; // 向下转型
                  sm.fly();
                  
              }
          }
          
          class Person {
              String name = "John";
          
              public void 谈生意() {
                  System.out.println("谈生意");
              }
          }
          
          class SuperMan extends Person {
              String name = "Super man";
          
              public void 谈生意() {
                  System.out.println("谈几个亿的大单子");
              }
          
              public void fly() {
                  System.out.println("飞出去救人");
              }
          }

    • 补充参考:基本数据类型:
      • 自动类型提升
      • 强制类型转换
      • class  Demo1_Polymorphic{
            public static void main(String[] args) {
                int i = 10;
                byte b = 20;
                i = b;  // 自动类型转换
                b = (byte)i;  // 强制类型转换
                
            }
        }
    • 多态的好处和弊端
      • 多态的好处
        • 提高了代码的维护性(继承保证)
        • 提高了代码的扩展性(由多态保证)
          • 可以当做形式参数
          • 可以接收任意子类对象
      • 多态的弊端
        • 不能使用子类的特有属性和行为
      • 案例演示
        • method(Animal a)  方便Animal的所有子类的 重写的方法调用
        • method(Cat c)  这种直接调用子类,出现并行子类,调用父类方法,需要些新的method方法,传入不同的类作为实参。
        • class Demo6_Polymorphic {
              public static void main(String[] args) {
                  
                  method(new Cat());
                  method(new Dog());  
                  /* 
                  Animal a = new Cat();
                  Animal a = new Dog();
                  
                  开发的时候很少在创建对象的时候用父类引用指向子类对象,
                  直接创建子类对象更方便,可以使用子类中的特有属性和方法
                  
                  */
          
              }
          
              /*
              public static void method(Cat c) {
                  c.eat();
              }
          
              public static void method(Dog d) {
                  d.eat();
              }*/
          
              public static void method(Animal a) { // 当做参数的时候,用多态最好,扩展性强
                  //关键字 instanceof 判断前边的引用是否是后边的数据类型
                  if (a instanceof Cat) {
                      Cat c = (Cat)a;
                      c.eat();
                      c.catchMouse();
                  }else if (a instanceof Dog) {
                      Dog d = (Dog)a;
                      d.eat();
                      d.lookHome();
                  }else {
                      a.eat();
                  }
          
                  
                  /*
                  // 如果把Dog强转成Cat,就会出现类型转换异常,ClassCastException
                  Cat c = (Cat)a;
                  c.eat();
                  c.catchMouse();*/
              }
          }
          
          class Animal {
              public void eat() {
                  System.out.println("动物吃饭");
                  }
          }
          
          class Cat extends Animal {
              public void eat() {
                  System.out.println("猫吃鱼");
              }
          
              public void catchMouse() {
                  System.out.println("抓老鼠");
              }
          }
          
          class Dog extends Animal {
              public void eat() {
                  System.out.println("狗吃肉");    
              }
          
              public void lookHome() {
                  System.out.println("看家");
              }
          }
          View Code 

    2. 抽象类

    • 抽象类概述
      • 抽象就是看不懂的
    • 抽象类的特点
      • 抽象类和抽象方法必须用abstract关键字修饰
        • abstract class 类名 ()
        • public abstract void eat();
      • 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者接口
      • 抽象类不能实例化,那么,抽象类如何实例化呢?
        • 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
      • 抽象类的子类
        • 要么是抽象类
        • 要么重写抽象类中的所有抽象方法
      • 案例演示
        • class Demo1_Abstract {
              public static void main(String[] args) {
          
                  Animal a = new Cat();
                  a.eat();
                  print(a);
              }
          
              public static void print(Animal a) {
                  a.eat();
              }
          }
          
          
          abstract class Animal { // 抽象类
               public abstract void eat();  // 抽象方法
          }
          
          
          class Cat extends Animal {
          
              public void eat() {
                  System.out.println("猫吃鱼");
              }
          
          }
          View Code
        • class Demo1_Abstract {
              public static void main(String[] args) {
          
                  
              }
          
              public static void print(Animal a) {
                  a.eat();
              }
          }
          
          
          abstract class Animal { // 抽象类
               public abstract void eat();  // 抽象方法
          }
          
          class Cat extends Animal {
          
              //错误: Cat不是抽象的, 并且未覆盖Animal中的抽象方法eat()
          
          }
          View Code
      • 抽象类联系(猫狗,抽象类为动物)
        • 具体事物:猫,狗
          共性:姓名,年龄,吃饭
          猫的特性:抓老鼠
          狗的特性:看家

        • class Test1_Animal {
              public static void main(String[] args) {
                  Cat c = new Cat("加菲",8);
                  System.out.println(c.getName() + "..." + c.getAge());
                  c.eat();
                  c.catchMouse();
          
                  Dog d = new Dog("八公",30);
                  System.out.println(d.getName() + "..." + d.getAge());
                  d.eat();
                  d.lookHome();
          
          
              }
          }
          
          /*
          案例演示:
          具体事物:猫,狗
          共性:姓名,年龄,吃饭
          猫的特性:抓老鼠
          狗的特性:看家
          */
          
          abstract class Animal {
              private String name;
              private int age;
          
              public Animal(){}
          
              public Animal(String name,int age) {
                  this.name = name;
                  this.age = age;
              }
          
              public void setName(String name) {  // 设置姓名
                  this.name = name;
              }
          
              public String getName() { // 获取姓名
                  return name;
              }
          
          
              public void setAge(int age) {  // 设置年龄
                  this.age = age;
              }
          
              public int getAge() { // 获取年龄
                  return age;
              }
          
          
              public abstract void eat();  // 抽象方法:吃饭
          }
          
          
          class Cat extends Animal {
              public Cat(){}
          
              public Cat(String name,int age) {
                  super(name,age);
              }
          
              public void eat() {
                  System.out.println("猫吃鱼");
              }
          
              public void catchMouse() {
                  System.out.println("抓老鼠");
              }
          }
          
          
          class Dog extends Animal {
              public Dog(){}
          
              public Dog(String name,int age) {
                  super(name,age);
              }
          
              public void eat() {
                  System.out.println("狗吃肉");
              }
          
              public void lookHome() {
                  System.out.println("抓老鼠");
              }
          }
          View Code
        • class Test2_Teacher {
              public static void main(String[] args) {
                  Teacher t = new BaseTeacher();
                  print(t);
          
                  print(new EmpTeacher());
                  
              }
              
              public static void print(Teacher t) {
                  t.teach();
              }
          }
          
          /*
          具体事物:基础班老师,就业班老师
          共性:姓名、年龄、讲课
          */
          
          abstract class Teacher {
              private String name;
              private int age;
              
              public abstract void teach();
          
          
              public Teacher() {}
          
              public Teacher(String name, int age) {
                  this.name = name;
                  this.age = age;
              }
          
              public void setName(String name) {
                  this.name = name;
              }
          
              public String getName() {
                  return name;
              }
          
              public void setAge(int age) {
                  this.age = age;
              }
          
              public int getAge() {
                  return age;
              }
          
          }
          
          class BaseTeacher extends Teacher {
              public BaseTeacher() {}
          
              public BaseTeacher(String name, int age) {
                  super(name, age);
              }
          
          
              public void teach() {
                  System.out.println("基础班老师 讲课");
              }
          
          }
          
          
          class EmpTeacher extends Teacher {
              public EmpTeacher() {}
          
              public EmpTeacher(String name, int age) {
                  super(name, age);
              }
          
          
              public void teach() {
                  System.out.println("就业班老师 讲课");
              }
          
          }
          老师抽象类
        • class Test3_Student {
              public static void main(String[] args) {
                  state(new BaseStudent());
                  state(new EmpStudent());
              }
          
              public static void state(Student s) {
                  s.study();
              }
          }
          
          
          /*
          具体事物:基础班学生,就业班学生
          共性:姓名,年龄,学习
          */
          
          abstract class Student {
              private String name;
              private int age;
              
              public abstract void study();
          
              public Student() {}
          
              public Student(String name, int age) {
                  this.name = name;
                  this.age = age;
              }
          
              public void setName(String name) {
                  this.name = name;
              }
          
              public String getNamge() {
                  return name;
              }
          
              public void setAge(int age) {
                  this.age = age;
              }
          
              public int getAge() {
                  return age;
              }
          
          }
          
          class BaseStudent extends Student {
              public BaseStudent() {}
          
              public BaseStudent(String name, int age) {
                  super(name,age);
              }
          
              public void study() {
                  System.out.println("基础班学生在学习");
              }
          }
          
          class EmpStudent extends Student {
              public EmpStudent() {}
          
              public EmpStudent(String name, int age) {
                  super(name,age);
              }
          
              public void study() {
                  System.out.println("就业班学生在学习");
              }
          }
          学生抽象类
        • class Test4_Employee {
              public static void main(String[] args) {
                  Coder c = new Coder("John", "001", 10000.00);
                  c.work();
          
                  Manager m = new Manager("Ann", "033", 40000.00, 10000);
                  m.work();
                  
              }
          }
          
          /*
          假如我们在开发一个系统时,需要对程序员类进行设计。
          程序员包含3个属性:
              姓名
              工号
              工资
          
          经理:出了含有程序员的属性外,还有一个奖金属性
          
          用继承的思想设计出程序员类和经理类。
          要求类中提供必要的方法进行属性访问。
          
          */
          
          abstract class Employee {
              private String name;
              private String code;
              private double salary;
          
              public Employee() {}
          
              public Employee(String name, String code, double salary) {
                  this.name = name;
                  this.code = code;
                  this.salary = salary;
              }
          
              public void setName(String name) {
                  this.name = name;
              }
          
              public String getName(){
                  return name;
              }
          
              public void setCode(String code) {
                  this.code = code;
              }
          
              public String getCode(){
                  return code;
              }
          
              public void setSalary(double salary) {
                  this.salary = salary;
              }
          
              public double getSalary(){
                  return salary;
              }
          
              public abstract void work();
          
              
          }
          
          
          class Manager extends Employee {
              private int bonus;
          
              public Manager() {}
          
              public Manager(String name, String code, double salary, int bonus) {
                  super(name,code,salary);
                  this.bonus = bonus;
              }
          
              public void setBonus(int bonus) {
                  this.bonus = bonus;
              }
          
              public int getBonus(){
                  return bonus;
              }
              
              
              public void work() {
                  System.out.println("项目经理" + this.getName() + "在工作");
                  System.out.println("奖金是" + this.getBonus());
              }
          
          }
          
          
          class Coder extends Employee {
              public Coder() {}
          
              public Coder(String name, String code, double salary) {
                  super(name,code,salary);
              }
              
              public void work() {
                  System.out.println("程序员" + this.getName() + "在工作");
              }
          
          }
          雇员:程序员,项目经理
    • 抽象类的注意问题
      • 一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
        • 可以。
          目的只有一个,就是不让其他类创建本类对象,交给子类完成
      • abstract不能和哪些关键字共存?

        • abstract 和 static
          被abstract修饰的方法没有方法体;
          被static修饰的可以用 类名.调用,但是类名.调用 抽象方法是没有意义的。

        • abstract 和 final 
          被abstract修饰的方法强制子类重写;
          被final修饰的方法,不让子类重写。这两个修饰词是矛盾的。

        • abstract 和 private
          被abstract修饰的是为了让子类看到并强制重写
          被private修饰的不让子类访问,所以他两是矛盾的。

        • class Demo4_Abstract {
              public static void main(String[] args) {
                  System.out.println("Hello World!");
              }
          }
          
          
          /*
          面试题1:
              一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
          答:
              可以。
              目的只有一个,就是不让其他类创建本类对象,交给子类完成
          
          面试题2:
              abstract不能和哪些关键字共存?
          答:
              abstract 和 static
              被abstract修饰的方法没有方法体;
              被static修饰的可以用 类名.调用,但是类名.调用 抽象方法是没有意义的。
          
              abstract 和 final 
              被abstract修饰的方法强制子类重写;
              被final修饰的方法,不让子类重写。这两个修饰词是矛盾的。
          
              abstract 和 private
              被abstract修饰的是为了让子类看到并强制重写
              被private修饰的不让子类访问,所以他两是矛盾的。
          
          
          */
          
          abstract class Demo {
              // public static abstract void print();
              // Demo4_Abstract.java:21: 错误: 非法的修饰符组合: abstract和static
              
              // public final abstract void print();
              // Demo4_Abstract.java:29: 错误: 非法的修饰符组合: abstract和final
              
              // private abstract void print();
              // Demo4_Abstract.java:36: 错误: 非法的修饰符组合: abstract和private
          }
          View Code

    3. 接口

    • 接口概述
      • 从狭义的角度讲,就是指java中的interface
      • 从广义的角度讲,就是对外提供规则的都是接口
    • 接口特点
      • 接口关键字interface表示
        • interface 接口名 {}
      • 类实现接口用 implements表示
        • class 类名 implements 接口名 {}
      • 接口不能实例化
        • 那么,接口如何实例化呢?
        • 按照多态的方式来实例化
      • 接口的子类
        • 可以是抽象类,但是意义不大。
        • 可以使具体类,要重写接口中的所有抽象方法(推荐方案)
    •  案例演示:接口特点
      • class Demo1_Interface {
            public static void main(String[] args) {
            //Inter i = new Inter();  // 接口不能被实例化,因为调用抽象方法没有意义
        
            Inter i = new Demo();
            i.print();
        
            }
        }
        
        interface Inter {
            public abstract void print(); // 接口中的方法都是抽象的
        }
        
        class Demo implements Inter {
            public void print() {
                System.out.println("print");
            }
        }
        接口类-子类是具体类,重写接口的 抽象方法(推荐)
      • class Demo1_Interface {
            public static void main(String[] args) {
        
        
            }
        }
        
        interface Inter {
            public abstract void print(); // 接口中的方法都是抽象的
        }
        
        abstract class Demo implements Inter {
            
        }
        接口-子类是抽象类(不推荐)
    • 接口的成员特点:

      • 成员变量

        • 只能是常量,并且是静态的,并公共的。
        • 默认修饰符:public static final(即使不手写,也会默认添加)
        • 建议:自己手动给出
      • 构造方法

        • 接口没有构造方法
      • 成员方法 

        • 只能是抽象方法
          • 默认修饰符:public abstract
          • 建议:自己手动给出
      • 案例演示
        • class Demo1_Interface {
              public static void main(String[] args) {
              
              Demo d = new Demo();
              d.print();
          
              System.out.println(Inter.num);
          
              }
          }
          
          interface Inter {
              public static final int num = 10;  // 系统会默认添加public static final,建议手动写出
              // 这三个关键词没有顺序区别
          
              // public Inter(){} 报错,接口中没有构造方法
              
              // public void print() {} // 接口中不能定义非抽象方法
          
              void print(); // 前面默认添加了public abstract修饰词
              public abstract void print2();
          }
          
          class Demo /* extends Object */ implements Inter {  // 一个类不写继承任何一个类,默认继承Object类
              public void print() {
                  
                  System.out.println(num);
              }
          
              public void print2() {}
          }
          View Code
        • class Test1_Aniaml {
              public static void main(String[] args) {
                  Cat c = new Cat("加菲",8);
                  c.eat();
                  c.sleep();
          
                  JumpCat jc = new JumpCat("跳高猫",3);
                  jc.eat();
                  jc.sleep();
                  jc.jump();
              }
          }
          
          /*
          动物类:姓名,年龄,吃饭,睡觉
          
          猫和狗
          
          动物培训接口:跳高
          */
          
          abstract class Animal {
              private String name;
              private int age;
          
              public Animal(){}
              public Animal(String name,int age){
                  this.name = name;
                  this.age = age;
              }
          
              public void setName(String name){
                  this.name = name;
              }
          
              public String getName(){
                  return name;
              }
          
              public void setAge(int age){
                  this.age = age;
              }
          
              public int getAge(){
                  return age;
              }
          
              public abstract void eat();
          
              public abstract void sleep();
          
          }
          
          interface Jumping {
              public void jump();
          }
          
          class Cat extends Animal {
              public Cat(){}
              public Cat(String name,int age){
                  super(name,age);
              }
          
              public void eat() {
                  System.out.println("猫吃鱼");
              }
          
              public void sleep() {
                  System.out.println("侧着睡");
              }
          
          }
          
          class JumpCat extends Cat implements Jumping {
              public JumpCat(){}
              public JumpCat(String name,int age){
                  super(name,age);
              }
          
              public void jump() {
                  System.out.println("猫跳高");
              }
          
          }
          动物:猫类,跳高的接口

    3. 各种类,接口之间的关系

    3.1 类与类,类与接口,接口与接口的关系

    • 类与类
      • 继承关系
        • 只能单继承,可以多层继承
    • 类与接口
      • 实现关系,可以单实现,也可以多实现
      • 并且还可以在继承一个类的同时实现多个接口
      • class Demo1_Interface {
            public static void main(String[] args) {
        
            }
        }
        
        
        
        interface InterA {
            public abstract void printA();
        }
        
        interface InterB {
            public abstract void printB();
        }
        
        class Demo implements InterA,InterB {
            public void printA() {
                System.out.println("printA");
            }
        
            public void printB() {
                System.out.println("printB");
            }
        }
        View Code
    • 接口与接口
      • 继承关系
        • 可以单继承,也可以多继承。
        • class Demo1_Interface {
              public static void main(String[] args) {
          
              }
          }
          
          
          
          interface InterA {
              public abstract void printA();
          }
          
          interface InterB {
              public abstract void printB();
          }
          
          interface InterC extends InterA,InterB {
          }
          View Code

     3.2 抽象类和接口的区别

    • 成员区别
      • 抽象类
        • 成员变量:可以变量,也可以常量
        • 构造方法:有
        • 成员方法:可以抽象,也可以非抽象
      • 接口
        • 成员变量:只可以常量
        • 成员方法:只可以抽象
    • 关系区别
      • 类与类
        • 继承,单继承
      • 类与接口
        • 实现,单实现,多实现
      • 接口与接口
        • 继承,单继承,多继承
    • 设计理念区别
    • 抽象类
      • 被继承体现的是“is a”的关系。
      • 抽象类中定义的是该继承体系的共性功能
    • 接口
      • 被实现体现的是“like a”的关系。
      • 接口中定义的是该继承体系的扩展功能

    4. 包package

    • 为什么要有包
      • 将字节码(.class)进行分类存放
      • 包其实就是文件夹
    • 包的概述
      • 举例:
        • 需求:
          • 学生:增加、删除、修改、查询
          • 老师:增加、删除、修改、查询
        • 方案1:按照功能分
          • com.heima.add
            • AddStudent
            • AddTeacher
          • com.heima.delete
            • DeleteStudent
            • DeleteTeacher
          • com.heima.update
            • UpdateStudent
            • UpdateTeacher
          • com.heima.find
            • FindStudent
            • FindTeacher
        • 方案2:按照模块分
          • com.heima.teacher
            • AddTeacher
            • DeleteTeacher
            • UpdateTeacher
            • FindTeacher
          • com.heima.student
            • AddStudent
            • DeleteStudent
            • UpdateStudent
            • FindStudent
    • 包的定义
      • 格式
        • package 包名;
        • 多级包用“.” 分开即可
      • 注意事项
        • package语句必须是程序的第一条可执行的代码
        • package语句在一个java文件中只能有一个
        • 如果没有package,默认表示无包名
      • 案例演示
        • package com.heima;
          // package语句必须是程序的第一条可执行的代码
          // 一个文件内只能有一个package语句
          
          
          class Demo1_Package {
              public static void main(String[] args) {
                  
              }
          }
    • 如何编译运行带包的类
      • 案例演示
        • javac编译时加上-d即可
          • javac -d . HelloWorld.java
        • 通过java命令执行
          • java 包名.HelloWorld
          • java com.heima.Demo1_Package
    • 不同包下类之间的访问
      • 案例演示
      • package com.heima;
        // package语句必须是程序的第一条可执行的代码
        // 一个文件内只能有一个package语句
        
        import com.baidu.Person;
        import com.xxx.Student;
        //import java.util.Scanner;        //在开发中我们用的都是导入具体的类
        import java.util.*;                //*代表通配符,他会到该包下挨个匹配,匹配上就导入
        class Demo1_Package {
            public static void main(String[] args) {
                Person p = new Person("张三",23);
                System.out.println(p.getName() + "..." + p.getAge());
                //p.print();            //在不同包下的无关类,不允许访问,因为是protected修饰的
        
                /*Scanner sc = new Scanner(System.in);
                int x = sc.nextInt();
                System.out.println(x);*/
                
                Student s = new Student("李四",24);
                System.out.println(s.getName() + "..." + s.getAge());
                s.method();
            }
        }
        View Code
    • import关键字的概述和使用 

      • 为什么要有import

        • 其实就是让有包的类对调用者可见,不用写全类名了

      • 导包格式

        • import 包名;

        • 注意:

          • 这种方式导入是到类的名称。

          • 虽然可以最后写*,但是不建议。

      • package,import,class有没有顺序关系
        • 有。
        • package 第一行,只能一个文件一句
        • import 中间,可以有多句
        • class 放在这两个下面

    5. 修饰符

    • 四种权限修饰符
      • private 本类;
      • 默认     本类;同一个包下(子类和无关类)
      • protected  本类;同一个包下(子类和无关类);不同包下(子类)
      • public   本类;同一个包下(子类和无关类);不同包下(子类);不同包下(无关类)
    • 修饰符
      • 权限修饰符:private,默认的,protected,public
      • 状态修饰符:static,final
      • 抽象修饰符:abstract
      • 权限修饰符:默认修饰符,public
      • 状态修饰符:final
      • 抽象修饰符:abstract
      • 用的最多的就是:public
    • 成员变量:

      • 权限修饰符:private,默认的,protected,public

      • 状态修饰符:static,final

      • 用的最多的就是:private

    • 构造方法:

      • 权限修饰符:private,默认的,protected,public

      • 用的最多的就是:public

    • 成员方法:

      • 权限修饰符:private,默认的,protected,public

      • 状态修饰符:static,final

      • 抽象修饰符:abstract

      • 用的最多的就是:public

    • 除此以外的组合规则:

      • 成员变量:public static final

      • 成员方法:

        • public static

        • public abstract

        • public final

    6. 内部类

    • 内部类概述

      • 在类中定义类,叫做内部类
    • 内部类访问特点

      • 内部类可以直接访问外部类的成员,包括私有。

      • 外部类要访问内部类的成员,必须创建对象。

      • 外部类名.内部类名 对象名 = 外部类对象.内部类对象;

    • 案例演示

      • class Demo1_InnerClass {
            public static void main(String[] args) {
                //Inner i = new Inner();
                //i.method();
                //外部类名.内部类名 = 外部类对象.内部类对象
                Outer.Inner oi = new Outer().new Inner();            //创建内部类对象
                oi.method();
        
            }
        }
        
        
        
        class Outer { // 外部类
            private int num = 10;
        
            class Inner {  // 内部类
                public void method() {
                    System.out.println(num);
                }
            }
        }
    • 内部类分类
      • 成员内部类
        • 成员内部类私有使用
          • class Demo2_InnerClass {
                public static void main(String[] args) {
                    //Outer.Inner oi = new Outer().new Inner(); //内部类私有,无法调用
                    //oi.method();
            
                    Outer o = new Outer();
                    o.print();
                }
            }
            
            class Outer {
                private int num = 10;
                
                private class Inner { //内部类私有
                    public void method() {
                        System.out.println(num);
                    }
                }
            
                public void print() {
                    Inner i = new Inner();  // 外部类,提供内部类实例化方法
                    i.method();
                }
            }
            内部类私有
          • class Test1_InnerClass {
                public static void main(String[] args) {
                    Outer.Inner oi = new Outer().new Inner();
                    oi.show();
                }
            }
            //要求:使用已知的变量,在控制台输出30,20,10。
            //内部类之所以能获取到外部类的成员,是因为他能获取到外部类的引用外部类名.this
            class Outer {
                public int num = 10;
                
                class Inner {
                    public int num = 20;
                    public void show() {
                        int num = 30;
                        System.out.println(num);
                        System.out.println(this.num);
                        System.out.println(Outer.this.num);
                    }
                }
            }
            成员内部类面试题:获取成员变量
      • 静态成员内部类
        • class Demo1_InnerClass {
              public static void main(String[] args) {
                  //外部类名.内部类名 对象名 = 外部类名.内部类对象;
                  Outer.Inner oi = new Outer.Inner();
                  oi.method();
          
                  Outer.Inner2.print();
              }
          }
          
          class Outer {
              
              static class Inner { // 静态成员内部类
                  public void method() {
                      System.out.println("method");
                  }
              }
          
              static class Inner2 {
                  public static void print() {
                      System.out.println("print");
                  }
              }
          }
          静态内部类
      • 局部内部类
        • 局部内部类,只能在其所在的方法中访问
        • 局部内部类访问局部变量的问题
          • 局部内部类访问局部变量必须用final修饰
          • 局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么?

            • 因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的,当方法弹栈,这个局部变量也会消失。

            • 那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了。

            • 如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可以继续使用。

            • 但是jdk1.8取消了这个事情,所以我认为这是个bug

          • class Demo1_InnerClass {
                public static void main(String[] args) {
                    Outer o = new Outer();
                    o.method();
                }
            }
            //局部内部类
            class Outer {
            
                public void method() {
                    final int num = 10;
                    //int num = 10; 错误:从内部类中访问本地变量num;需要被声明为最终类型。final
            
                    class Inner {   // 局部内部类
                        public void print() {
                            System.out.println(num);
                        }
                    }
            
                    Inner i = new Inner(); //只能在局部所在的方法中访问
                    i.print();
                }
            
                /*public void run() {
                    Inner i = new Inner();        //局部内部类,只能在其所在的方法中访问
                    i.print();
                }*/
            }
            局部内部类示例,final修饰符修饰变量
      • 匿名内部类
        • 就是内部类的简化写法。
        • 前提:
          • 存在一个类或者接口
          • 这里的类可以是具体类也可以是抽象类。
        • 格式
          • new 类名或者接口名() {
                重写方法;
            }

        • 本质是什么呢?
          • 是一个继承了该类或者实现了该接口的子类匿名对象。
        • 案例演示
          • class Demo1_NoNameInnerClass {
                public static void main(String[] args) {
                    Outer o = new Outer();
                    o.method();
                }
            }
            
            
            interface Inter {
                public void print();
            }
            
            class Outer {
            
                /*class Inner implements Inter {  // 这是有名字的内部类,继承Inter接口
                    public void print() {
                        System.out.println("print");
                    }
                }*/
            
                public void method(){
                    //Inner i = new Inner();
                    //i.print();
                    //new Inner().print();
                    //Inter i = new Inner();            //父类引用指向子类对象
                    
                    new Inter() {                        //实现Inter接口
                        public void print() {            //重写抽象方法
                            System.out.println("print");
                        }
                    }.print();     //
                }
            }
            匿名内部类:单个方法调用
          • class Demo2_NoNameInnerClass {
                public static void main(String[] args) {
                    Outer o = new Outer();
                    o.method();
                }
            }
            
            interface Inter {
                public void show1();
                public void show2();
            }
            //匿名内部类只针对重写一个方法时候使用
            class Outer {
                public void method() {
                    /*new Inter(){
                        public void show1() {
                            System.out.println("show1");
                        }
            
                        public void show2() {
                            System.out.println("show2");
                        }
                    }.show1();
            
                    new Inter(){
                        public void show1() {
                            System.out.println("show1");
                        }
            
                        public void show2() {
                            System.out.println("show2");
                        }
                    }.show2();*/
            
                    Inter i = new Inter(){
                        public void show1() {
                            System.out.println("show1");
                        }
            
                        public void show2() {
                            System.out.println("show2");
                        }
            
                        /*public void show3() {
                            System.out.println("show3");
                        }*/
                    };
            
                    i.show1();
                    i.show2();
                    //i.show3();  //匿名内部类是不能向下转型的,因为没有子类类名
                }
            }
            匿名内部类只针对重写一个方法时候使用
        • 匿名内部类在开发中的应用
          • class Test1_NoNameInnerClass {
                public static void main(String[] args) {
                    //如何调用PersonDemo中的method方法呢?
                    PersonDemo pd = new PersonDemo ();
                    //pd.method(new Student());
                    pd.method(new Person() {
                        public void show() {
                            System.out.println("show");
                        }
                    });
                }
            }
            //这里写抽象类,接口都行
            abstract class Person {
                public abstract void show();
            }
            
            class PersonDemo {
                
                //public void method(Person p) {        //Person p = new Student();        //父类引用指向子类对象
                /*
                Person p = new Person(){
                    public void show() {
                        System.out.println("show");
                    }
                };
                */
                public void method(Person p) {
                    p.show();
                }
            }
            
            class Student extends Person {
                public void show() {
                    System.out.println("show");
                }
            }
            匿名内部类在开发中,当做参数传递(把匿名内部类当做一个对象)
          • class Test2_NoNameInnerClass {
                public static void main(String[] args) {
                    //Outer.method().show();            //链式编程,每次调用方法后还能继续调用方法,证明调用方法返回的是对象
                    Inter i = Outer.method();
                    i.show();
                }
            }
            //按照要求,补齐代码
            interface Inter { 
                void show(); 
            }
            
            class Outer { 
                //补齐代码 
                public static Inter method() {
                    return new Inter() {
                        public void show() {
                            System.out.println("HelloWorld");
                        }
                    };
                }
            }
            
            //要求在控制台输出”HelloWorld”
            根据主方法的调用方法,补齐代码
  • 相关阅读:
    关于React的脚手架
    yarn和npm
    谈谈NPM和Webpack的关系
    php开发环境和框架phalcon的搭建
    Centos6.5--svn搭建
    System.Diagnostics.Process.Start(ProcessStartInfo)
    PHP错误:call to undefined function imagecreatetruecolor
    PostgreSQL删除表中重复数据行
    URL存在http host头攻击漏洞-修复方案
    for循环的执行顺序
  • 原文地址:https://www.cnblogs.com/zoe233/p/12759781.html
Copyright © 2011-2022 走看看