zoukankan      html  css  js  c++  java
  • 类,接口

    1. 面向对象

    1.1. 类的定义

    • 语法格式:

      public class 类名称{
          String name; //成员变量
          public void eat(){
              String first_name; //局部变量
          }//成员方法
      }
      
    • 定义类: 就是定义类的成员,包括成员变量,成员方法

    1. 对象的使用
    1. 创建对象:

      类名 对象名 = new 类名();
      
    2. 使用对象访问勒种的成员:

      对象名.成员变量;
      对象名.成员方法;
      

    2. 封装

    1. 原则

    • 讲成员变量进行隐藏,如果需要使用的时候,通过公共方法进行设置和获取

    2. 步骤

    1. 使用private关键字来修饰成员变量。
    2. 对需要访问的成员变量,提供对应的一对 getXXX方法、setXXX方法

    3. 封装的操作---private关键字

    private的含义:
    1. private是一个权限修饰符,代表的是最小权限。
    2. 可以修饰成员变量和成员方法。
    3. 被private修饰后的成员变量和成员方法,只能在本类中进行使用
    private的使用格式:
    prviate 数据类型 变量名;
    
    1. 使用private修饰成员变量,代码

      public class Student{
          private String name;
          private int age;
      }
      
    2. 提供getset方法,可以访问成员变量,代码

      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 num){
              age = num;
          }
          public int getAge(){
              return age;
          }
      }
      

    4. 封装的关键字----this关键字

    this的含义:
    • this代表坐在类的当前对象的(地址值), 即对象的自己的引用

      | 记住: 方法被那个对象调用,那么this代表的是哪个对象

    this的使用格式:
    this.成员变量名;
    

    使用this关键字修饰方法中的比那里,解决成员变量被隐藏的问题

    public class Student{
        private String name;
        private int age;
        public void setName(String n){
            this.name = n;
        }
        public String getName(){
            return name;
        }
        public void setAge(int num){
            this.age = num;
        }
        public int getAge(){
            return age;
        }
    }
    

    小贴士:方法中只有一个变量名时,默认也是使用 this 修饰,可以省略不写。

    5. 构造方法(类似于python中 new 方法)

    • 当一个对象被创建时候,构造方法用来初始化该对象,给对象的成员变量赋初始值。
    • 小贴士:无论你与否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个无参数构造方法,一旦自己定义了构造方法,Java自动提供的默认无参数构造方法就会失效。
    构造方法的定义格式:
    修饰符 类名称(参数列表){
        // 方法体
    }
    
    public class Teach{
        private String name;
        private int age;
        public Teach(){} // 无参构造 系统会默认赠送一个
        public Teach(String name,int age){ // 带参数的构造
            this.age = age;
            this.name = name;
        }
        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;
        }
    }
    

    构造方法的写法上,方法名与它所在的类名相同。它没有返回值,所以不需要返回值类型,甚至不需要void。

    注意事项:

    1. 如果你不提供构造方法,系统会给出无参数构造方法。
    2. 如果你提供了构造方法,系统将不再提供无参数构造方法。
    3. 构造方法是可以重载的,既可以定义参数,也可以不定义参数。

    6. 标准化代码----JavaBean

    JavaBean 是 Java语言编写类的一种标准规范。符合 JavaBean的类,要求类必须是具体的和公共的,并且具有无参数的构造方法,提供用来操作成员变量的 set 和 get 方法

    具体格式:
    public class ClassName{
    //成员变量
    //构造方法
    //无参构造方法【必须】
    //有参构造方法【建议】
    //成员方法
    //getXxx()
    //setXxx()
    }
    

    3. 继承

    定义:继承:就是子类继承父类的属性和行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。

    好处

    1. 提高代码的复用性。
    2. 类与类之间产生了关系,是多态的前提

    1. 继承的格式

    通过extends关键字

    public class 父类{
        ...
    }
    public class 子类 extends 父类{
        ...
    }
    
    • 案例:

      public class Employee{
          String name; //定义name属性
          public void work(){
              System.out.println("努力工作");
          }
      }
      
      public class Teacher extends Employee{
          // 定义打印name的方法
          public void printName(){
              System.out.println("name:"+name);
          }
      }
      
      public class testDemo{
          public static void main(String[] args){
              // 创建一个讲师的对象
              Techer t = new Teacher();
              
              // 进行name赋值
              t.name = "孔老师";
              t.printName();
              t.work();
          }
      }
      

    2. 继承的特点---成员变量

    成员变量不重名
    • 如果子类和父类中出现不重名的成员变量,这是访问没有任何问题

      public class Fu{
          // Fu中的成员变量
          int num = 5;
      }
      
      public class Zi extents Fu{
          // 子类的成员变量
          int num2 = 10;
          public void show(){
              // 访问父类的num
              System.out.println("Fu num:"+num);
              // 访问子类的num2
              System.out.println("Zi num2:"+num2);
          }
      }
      
      public class Demo{
          public static void main(String[] args){
              Zi z = new Zi();
              z.show();
          }
      }
      
      // 5
      // 10
      
    成员变量重名
    • 使用格式

      super.父类成员变量名
      
      

      子类方法需要修改:

      public class Zi extends Fu{
          //子中的成员变量
          int num = 10;
          public void show(){
              System.out.println("Fu num:"+super.num);
              System.out.println("Zi num:"+this.num);
          }
      }
      
      
    小贴士:

    Fu 类中的成员变量是非私有的,子类中可以直接访问。若Fu 类中的成员变量私有了,子类是不能直接访问的。通常编码时,我们遵循封装的原则,使用private修饰成员变量,那么如何访问父类的私有成员变量呢?对!可以在父类中提供公共的getXxx方法和setXxx方法。

    3. 继承后的特点---成员方法

    成员方法不重名

    如果子类父类中出现不重名的成员方法,这时的调用是没有影响的。对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。代

    • 代码:

      class Fu{
          public void show(){
          	System.out.println("Fu类中的show方法执行");
          }
      }
      class Zi extends Fu{
          public void show2(){
          	System.out.println("Zi类中的show2方法执行");
      	}
      }
      public class ExtendsDemo04{
          public static void main(String[] args) {
          	Zi z = new Zi();
      		//子类中没有show方法,但是可以找到父类方法去执行
      		z.show();
      		z.show2();
      	}
      }
      
      
    成员方法重名-----重写(Override)
    方法重写:
    • 子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效 果,也称为重写或者复写。声明不变,重新实现。

      public class Phone{
          public void send(){
              System.out.println("发短信");
          }
          public void reverse(){
              System.out.println("接电话");
          }
          public void show(){
              System.out.println("显示来电号码");
          }
      }
      
      
      public class NewPhone extends Phone{
          public void show(){
             	super.show();
              System.out.println("显示头衔");
              System.out.println("显示姓名");
          }
      }
      
      
      public class testDemo{
          public static void main(String[] args){
              NewPhone nh = new NewPhone();
              nh.show();
          }
      }
      
      
      小贴士:这里重写时,用到super.父类成员方法,表示调用父类的成员方法
    注意事项
    1. 子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
    2. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。

    4. 继承后的特点--构造方法

    1. 构造方法的定义格式和作用
    1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。

    2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构 造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。

      代码:

      public class Fu{
          private int n;
          public Fu(){
              System.out.println("我是父类的构造方法");
          }
      }
      
      
      public class Zi extends Fu{
          public Zi(){
              super(); //父类的构造方法
              System.out.println("我是子类的构造方法");
          }
      }
      
      
      public class Demo{
          public static void main(String[] args){
              Zi z = new Zi();
          }
      }
      
      

    5. super和this

    super和this的含义
    • super :代表父类的存储空间标识(可以理解为父亲的引用)。
    • this :代表当前对象的引用(谁调用就代表谁)。
    super和this的用法
    1. 访问成员
    this.成员变量;   ---本类的
    super.成员变量;  ---父类的
    this.成员方法名();	---本类的
    super.成员方法名();	---父类的
    
    
    2. 访问构造
    this();   -- 本类的构造方法
    super();  -- 父类的构造方法
    
    
    • 子类的每个构造方法中均有默认的super(),调用父类的空参构造。手动调用父类构造会覆盖默认的super()。super() 和 this() 都必须是在构造方法的第一行,所以不能同时出现。

    6. 继承的特点

    1. java只支持单继承,不支持多继承
    2. java支持多层继承(继承体系)
    3. 子类和父类是一种相对的概念

    4. 抽象类

    1. 什么是抽象类

    1.定义
    • 抽象方法: 没有方法体的方法
    • 抽象类:包含抽象方法的类

    2.使用格式

    抽象方法

    使用abstract关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体

    定义格式
    修饰符 abstract 返回值类型 方法名(参数列表);
    
    

    例子:

    public abstract void run();
    
    
    抽象类

    如果一个类包含抽象方法那么这个类就是抽象类

    定义格式
    修饰符 abstract class 类名称{};
    
    

    例子:

    public abstract class Animal{
        public abstract void run();
    }
    
    
    抽象的作用

    继承抽象类的子类必须重写父类所有的抽象方法.否则,该子类也必须申明维持抽象类.最终,必须要有子类实现父类的抽象方法; 这种过程是: 实现方法

    3. 注意事项

    1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
      • 理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
    2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
      • 理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
    3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
      • 理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
    4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象 类。
      • 理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

    5. 接口

    1. 什么是接口

    • 接口:一种引用数据类型,接口不可以创建对象,但是可以被实现implements。一个实现接口的类(可以看做是接口的子类),需要实现接口中所有的抽象方法,创建该类对象,就可以调用方法,否则就是一个抽象类

    2.定义格式

    public interface 接口名称{
      // 抽象方法
      // 默认方法
      // 静态方法
      //私有方法
    }
    
    
    含有抽象方法
    抽象方法: 使用abstract关键字进行修饰,可以省略,没有方法体,供子类进行实现使用
    public interface 接口名字{
      public abstract void 方法名称();
    }
    
    
    含有默认方法和静态方法
    默认方法: 使用default修饰,不可以省略,供子类调用或者子类重写。
    静态方法:使用static修饰,供接口直接调用。
    public interface 接口名字{
      public default void 方法名(){
        // 执行语句
      }
      public static void 方法名(){
        // 执行语句
      }
    }
    
    
    含有私有方法和私有静态方法
    私有方法:使用private修饰,供接口中的默认方法或者静态方法调用
    public interface 接口名称{
      private void 方法名(){
        // 执行语句
      }
    }
    
    

    3.基本的实现

    实现的概述

    类与接口的关系为实现关系,即类实现接口,该类可以成为接口的实现类 使用implements关键字

    非抽象子类实现接口:

    1. 必须重写接口里面所有的抽象方法
    2. 继承接口的默认方法,可以直接调用,也可以重写

    实现格式:

    public class 类名 implements 接口名{
      // 重写接口中的抽象方法
      // 调用接口的默认方法或者重写
    }
    
    
    抽象方法的使用

    必须全部实现

    定义接口:

    public interface 接口名{
      // 定义抽象方法
      public abstract void 抽象方法名1();
      public abstract void 抽象方法名2();
    }
    
    

    定义实现类:

    public class 类名 implements 接口名称{
      @Override
      public void 抽象方法名1(){
        // 语句块
      }
      @Override
      public void 抽象方法名2(){
        // 语句块
      }
    }
    
    

    定义使用类:(对象)

    public class 类名称{
      public static void main(String[] args){
        // 创建子类对象
        类名 类实例对象 = new 类名();
        // 调用实现后的方法
        类实例对象.抽象方法名1()类实例对象.抽象方法名2();
      }
    }
    
    
    默认方法的使用

    可以重写,可以继承,只能通过实现类的对象来调用

    1.继承默认方法

    定义接口:

    public interface LiveAble{
      public default void fly(){
        System.out.println("天上飞");
      }
    }
    
    

    定义实现类:

    public class Animal implements LiveAble{
      //继承,什么都不用写,直接调用
    } 
    
    

    定义测试类:

    public class InterFaceDemo{
      public static void main(String[] args){
        // 创建子类对象
        Animal a = new Animal();
        // 调用默认方法
        a.fly();
      }
    }
    
    
    2.重写默认方法

    定义接口:

    public interface LiveAble{
      public default void fly(){
        System.out.println("天上飞");
      }
    }
    
    

    定义实现类:

    public class Animal implements LiveAble{
      @Override
      public void fly(){
        System.out.println("自由自在的飞");
      }
    }
    
    

    定义测试类:

    public class InterfaceDemo{
      public static void main(String[] args){
        // 创建子类对象
        Animal a = new Animal();
        // 调用重写方法
        a.fly();
      }
    }
    
    
    静态方法的使用

    静态方法和.class文件相关,只能使用接口名调用,不可以使用实现类的类名或者实现类的对象调用

    定义接口:

    public interface LiveAble{
      public static void run(){
        System.out.println("跑起来");
      }
    }
    
    

    定义实现类:

    public class Animal implements LiveAble{
      // 无法重写静态方法
    }
    
    

    定义测试类:

    public class InterfaceDemo{
      public static void main(String[] args){
        LiveAble.run();
      }
    }
    
    
    私有方法的使用
    • 私有方法:只有默认方法可以调用
    • 私有静态方法:默认方法和静态方法可以调用

    定义接口:

    public interface LiveAble{
      default void func(){
        func1();
        func2();
      }
      private void func1(){
        // 语句块
      }
      private void func2(){
        // 语句块
      }
    }
    
    

    4.接口的多实现

    接口可以多实现

    实现各式:

    public class 类名 implements 接口1,接口2{
      // 重写接口里面的抽象方法
      // 重写接口中的默认方法(不重名可选)
    }
    
    
    抽象方法

    如果抽象方法有重名,只需要写一次

    定义多个接口:

    public interface A{
      public abstract void showA(){}
      public abstract void show(){}
    }
    
    public interface B{
      public abstract void show(){}
      public abstract void showB(){}
    }
    
    

    定义实现类:

    public class C implements A,B{
      @Override
      public void showA(){
        // 语句块
      }
      @Override
      public void showB(){
        // 语句块
      }
      @Override
      public void show(){
        // 语句块
      }
    }
    
    
    默认方法

    如果默认方法有重名的,必须重写一次

    定义多个接口:

    public interface A{
      public default void methodA();
      public default void method();
    }
    
    public interface B{
      public default void methodB();
      public default void method();
    }
    
    

    定义实现类:

    public class C implements A,B{
      @Override
      public void method(){
        // 语句块
      }
    }
    
    
    静态方法

    接口中,存在同名的静态方法不会冲突。原因是通过接口名称访问静态方法

    优先级问题

    当一个类,既继承一个父类,又实现多个接口时,父类中的成员方法和接口中的默认方法重名时,子类选择父类的成员方法(就近原则)

    接口的多继承

    一个接口继承一个或者多个接口,接口继承使用extends关键字

    如果父类接口中有默认方法重名的,那么子类接口需要重写一次

    • 子接口重写默认方法的时候,default关键字可以保留
    • 子类重写默认方法时,default关键字不可以保留

    5.其他成员特点

    • 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰
    • 接口中,没有构造方法,不能创造对象
    • 接口中,没有静态代码块

    6. 多态

    • 多态:指同一行为,具有多个不同表现形式

    1.多态的体现

    父类类型 变量名 = new 子类对象;
    变量名.方法名();
    
    

    父类类型:值子类对象继承的父类类型或者是实现父类接口类型

    当时用多态方式调用方法时,首先先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是自而立重写后的方法

    定义父类:

    public abstract class Animal{
      public abstract void eat();
    }
    
    

    定义子类:

    class Cat extends Animal{
      public void eat(){
        System.out.println("吃鱼");
      }
    }
    
    class Dog extends Animal{
      public void eat(){
        System.out.println("吃骨头");
      }
    }
    
    

    定义测试类:

    public class Test{
      public static void main(String[] args){
        //多态形式,创建对象
        Animal a = new Cat();
        a.eat(); // cat的eat
        Animal b = new Dog();
        b.eat(); // dog的eat
      }
    }
    
    

    2.引用数据转换

    1.向上转型
    • 向上转型:多态本身就是子类向父类类型向上转换的过程,这个过程是默认的

    当弗雷引用指向一个子类对象时,便是向上转型。

    使用格式:

    父类类型 变量名 = new 子类类型();
    例子: Animal a = new Cat()
    2.向下转型
    • 向下转型:父类类型向子类类型向下转换的过程,这个过程就是强制的。

    使用格式:

    子类类型 变量名 = (子类类型) 父类变量名;
    例子: Cat c = (Cat) a;
    
    
    为什么要转型

    当我们使用多肽调用方法的时候,首先是检查父类中是否有该方法,如果没有,则编译报错。也就是说,不能调用子类拥有,而弗雷没有的方法,编译出错。所以想要用子类特性的方法,必须向下转型。

    定义类:

    public abstract class Animal{
      abstract void eat();
    }
    
    public class Cat extends Animal{
      public void eat(){
        System.out.println("吃鱼");
      }
      public void catchMouse(){
        System.out.println("抓老鼠");
      }
    }
    
    public class Dog extends Animal{
      public void eat(){
        System.out.println("吃骨头");
      }
      public void watchHouse(){
        System.out.println("看家");
      }
    }
    
    

    定义测试类:

    public class Test{
      public static void main(String[] args){
        // 向上转型
        Animal a = new Cat();
        a.eat(); // cat的eat
        
        // 向下转型
        Cat c = (Cat) a;
        c.catchMouse();  // cat的catchHouse
      }
    }
    
    
    转型的异常
    public class Test{
      public static void main(String[] args){
        // 向上转型
        Animal a = new Cat();
        a.eat(); // cat的eat
        
        // 向下转型
        Dog d = (Dog) a;
        c.watchHouse();  // dog的watchHouse 运行报错
      }
    }
    
    

    这段代码可以通过编译,但是会报错,报了classCatException 类型转换异常。因为我们创建的是一个Cat类型对象,运行的时候,不能转换为Dog对象,不符合转型的定义。为了避免这种情况,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
        }
      }
    }
    
    

    7.内部类

    1.什么是内部类

    将一个类A定义到另一个类B里面,里面的那个类A就是内部类,B就是外部类

    成员内部类
    • 成员内部类: 定义在类中方法外的类

    定义格式:

    public class 外部类{
      public class 内部类{
      }
    }
    
    

    代码举例:汽车和发动机

    public class Car{ //外部类
      public class Engine{
        // 内部类
      }
    }
    
    
    访问特点
    • 内部类可以直接访问外部类的成员,包括私有成员

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

    • 创建格式:

      外部类名.内部类名 对象名 = new 外部类型().new内部类型();
      
      

    定义类:

    public class Person{
      private bpplean live = true;
      public class Heart{
        public void jump(){
          // 直接访问外部类成员
        if(live){
          System.out.println("心脏在跳动");
        }else{
          System.out.println("心脏不跳了");
        }
        }
      }
      public boolean isLive(){
        return live;
      }
      public void setLive(boolean live){
        this.live = live;
      }
    }
    
    

    定义测试类:

    public class InnerDemo{
      public static void main(String[] args){
        // 创建外部类对象
        Person p = new Person();
        // 创建内部类对象
        Person.Heart h = new Person().new Heart();
        // 调用内部方法
        h.jump();
        // 调用外部类方法
        p.setLive(false);
        // 调用内部类方法
        h.jump();
      }
    }
    
    

    注意: 内部类是一个独立的类,在编译之后会在内部类会被编译成独立的.class文件,但是前面必须是以外部类的类名和符号。 例如:Person$Heart.class

    2.匿名内部类

    • 匿名内部类:是内部类的简化写法,本质是一个带具体实现的父类或者是父接口的匿名的子类对象。

    使用接口的步骤:

    1. 定义子类
    2. 重写接口中的方法
    3. 创建子类对象
    4. 调用重写后的方法
    前提

    匿名内部类必须是一个继承一个父类或者实现一个父接口

    格式
    new 父类名或者接口名(){
      //方法重写
      @Override
      public void method(){
        // 执行语句
      }
    }
    
    
    使用方式

    接口为例子

    定义接口:

    public abstract class FlyAble{
      public abstract void fly();
    }
    
    

    创建爱你匿名内部类并进行调用:

    public class Demo{
      public static void main(String[] args){
        /*
        1.等号左边:是多态赋值操作,接口类型引用子类对象
        2.等号右边:是匿名内部类,定义并创建该接口的子类对象
        */
        FlyAble f = new FlyAble(){
          public void fly(){
            System.out.println("我飞了");
          }
        };
        f.fly();
      }
    }
    
    

    通常在方法的形式参数是接口或者抽象类时,也可以将匿名对象作为参数

    public class Demo2{
      public static void main(String[] args){
        /*
        等号左边:是多态,接口类型引用指向子类对象
        等号右边:定义并创建该接口的子类对象
        */
        FlyAble f = new FlyAble(){
          public void fly(){
            System.out.println("我飞了");
          }
        };
        // 将f传递给showFly方法中
        showFly(f);
      }
      public static void showFly(FlyAble f){
        f.fly();
      }
    }
    
    

    简化:

    public class Demo3{
      public static void main(String[] args){
        showFly(new FlyAble(){
      			public void fly(){
        			System.out.println("我飞了");
      			}
    		});
      }
      public static void showFly(FlyAble f){
        f.fly();
      }
    }
    

     

  • 相关阅读:
    云计算和大数据时代网络技术揭秘(十九)万兆革命 (完)
    云计算和大数据时代网络技术揭秘(十八)刀片服务器的网络
    云计算和大数据时代网络技术揭秘(十七)VOQ机制
    云计算和大数据时代网络技术揭秘(十六)数据中心布线
    云计算和大数据时代网络技术揭秘(十五)大数据网络
    云计算和大数据时代网络技术揭秘(十四)虚拟桌面
    云计算和大数据时代网络技术揭秘(十三)VXLAN
    python3练习100题——037
    python3练习100题——036
    python3练习100题——035
  • 原文地址:https://www.cnblogs.com/liudemeng/p/11343861.html
Copyright © 2011-2022 走看看