Java三大特性

48 阅读6分钟

一、封装

1.1 为什么要封装

  • 有些数据语法上是可以的,在生产中是非法的

    • 年龄20000
    • 工资-10000

1.2 封装的流程

1、私有化属性【private】

2、提供公开的setXxx和getXxx方法

3、在方法中制定访问规则

1.3 封装案例

Student

package com.shine.private0;
​
/**
 *  类名
 *      Student
 *  属性
 *      学号
 *      姓名
 *      年龄
 *      信息
 *  方法
 *      展示
 */
public class Student {
    // 属性
    String stuNo;
    String name;
    // 私有的属性,只能在当前类中使用
    private int age;
    String info;
    
    /**
     *  读取数据
     * @return
     */
    public int getAge() {
        return age;
    }
    
    /**
     *  设置数据
     * @param age
     */
    public void setAge(int age) {
        // 过滤非法数据
        if (age>0 && age<130) {
            this.age = age;
        } else {
            System.err.println("非法年龄:" + age);
            this.age = -1;  // 尝试设置非法的年龄,把年龄设置为-1
        }
    }
    
    public void show() {
        System.out.println("Student [stuNo=" + stuNo + ", name=" + name + ", age=" + age + ", info=" + info + "]");
    }
    
}

TestStudent

package com.shine.private0;
​
public class TestStudent {
    public static void main(String[] args) {
        // 创建对象
        Student stu = new Student();
        
        // 属性赋值
        stu.stuNo = "20191012066";
        stu.name = "张三";
        //stu.age = 22; // 私有的属性不能再类的外部直接访问
        stu.info = "法外狂徒";
        stu.setAge(22);
        System.out.println(stu.getAge());
    
        // 调用方法展示信息
        stu.show();
        
        // 修改属性
        //stu.age = 233;
        stu.setAge(233);
        stu.show();
    }
}

Phone

package com.shine.private0;
​
public class Phone {
    // 属性
    private String brand;
    private String model;
    private String color;
    private double price;
    private String info;
​
    public String getBrand() {
        return brand;
    }
​
    public void setBrand(String brand) {
        String[] brands = {"苹果","三星","华为","中兴","联想","摩托罗拉"};
        this.brand = "不存在";
        for (int i = 0; i < brands.length; i++) {
            if (brand.equals(brands[i])) {
                this.brand = brand;
                break;
            }
        }
    }
​
    public String getModel() {
        return model;
    }
​
    public void setModel(String model) {
        this.model = model;
    }
​
    public String getColor() {
        return color;
    }
​
    public void setColor(String color) {
        this.color = color;
    }
​
    public double getPrice() {
        return price;
    }
​
    public void setPrice(double price) {
        if (price>0 && price<1000000) {
            this.price = price;
        } else {
            this.price = -1;
        }
    }
​
    public String getInfo() {
        return info;
    }
​
    public void setInfo(String info) {
        this.info = info;
    }
​
}

二、继承

2.1 概述

生活中的继承

  • 后辈从先辈那里继承得到财、物
  • 后辈从先辈获取基因

程序中的继承

  • 子类获取到父类中的属性和方法

2.2 继承语法

class A{}
class B extends A{}
class C extends B{}
​
B能得到A中的属性和方法
C得到AB中的属性和方法
​
Java是单继承,Java支持多级继承

2.3 继承入门案例

  • 动物世界
package com.shine.extends0;
​
public class Demo01 {
    public static void main(String[] args) {
        /**
         *  编写代码展示动物世界中的动物
         */
        // 创建对象
        Lion lion = new Lion();
        Ratel ratel = new Ratel();
        TheHyena hyena = new TheHyena();        
    }
}
​
/**
 *  狮子类
 */
class Lion{
    String breed;
    String name;
    int age;
    String sex;
    String color;
    String weight;
    double height;
    double length;
    
    public void eat() {
        
    }
    
    public void sleep() {
        
    }
    
    public void hunt() {
        
    }
}
​
/**
 *  羊驼
 */
class Alpaca{
    String breed;
    String name;
    int age;
    String sex;
    String color;
    String weight;
    double height;
    double length;
    
    public void eat() {
        
    }
    
    public void sleep() {
        
    }
    
    public void climbTree() {
        
    }
    
    public void run() {
        
    }
    
}
​
/**
 *  鳄鱼
 */
class Crocodile {
    String breed;
    String name;
    int age;
    String sex;
    String color;
    String weight;
    double height;
    double length;
    
    public void eat() {
        
    }
    
    public void sleep() {
        
    }
    
    public void swim() {
        
    }
    
    public void climb() {
        
    }
}
​
/**
 *  蓝鹤
 */
class BlueCrane{
    String breed;
    String name;
    int age;
    String sex;
    String color;
    String weight;
    double height;
    double length;
    
    public void eat() {
        
    }
    
    public void sleep() {
        
    }
    
    public void fly() {
        
    }
}
​
/**
 *  所有动物中抽取共性的属性和方法,形成Animal这个类
 */
class Animal {
    String breed;
    String name;
    int age;
    String sex;
    String color;
    String weight;
    double length;
    
    public void eat() {
        
    }
    
    public void sleep() {
        
    }
}
​
class Ratel {
    
}
​
class TheHyena extends Animal{
    double height;
    
    public void hunt() {
        
    }
    
    public void run() {
        
    }
}

2.4 继承案例

Worker

package com.shine.extends0;
​
/**
 *  类名
 *      工人
 *  属性
 *      种类
 *      姓名
 *      年龄
 *      工资
 *      信息
 *  方法
 *      吃饭
 *      睡觉
 *      工作
 */
public class Worker {
    String type;
    String name;
    int age;
    double salary;
    String info;
    
    public void eat() {
        System.out.println("工人需要吃饭");
    }
    
    public void sleep() {
        System.out.println("工人需要睡觉");
    }
    
    public void work() {
        System.out.println("工人需要工作");
    }
}

Cook

package com.shine.extends0;
​
/**
 *  类名
 *      厨师
 *      继承Worker,得到属性和方法
 */
public class Cook extends Worker{
    // 属性
    
    // 方法
    public void cook() {
        System.out.println("厨师做饭");
    }
    
    public void teastFood() {
        System.out.println("厨师需要试菜");
    }
    
}

2.5 不可继承

父类中的构造方法

  • 构造方法只负责本类类型对象的创建

父类中私有的属性和方法

  • 受访问权限修饰符限制,访问范围只能在当前类中

三、访问修饰符

3.1 概述

  • 修饰属性、方法、类的修饰符
  • 限制数据在不同位置的可见性

3.2 修饰符和范围

3.3 案例代码

modify01.FFF

package com.shine.modify01;
​
public class FFF {
    public String publicStr = "publicStr";
    protected String protectedStr = "protectedStr";
    String defaultStr = "defaultStr";
    private String privateStr = "privateStr";
    
    /**
     *  在同类中能访问的内容:
     *      public
     *      protected
     *      default
     *      private
     */
    public void show() {
        System.out.println(publicStr);
        System.out.println(protectedStr);
        System.out.println(defaultStr);
        System.out.println(privateStr);
    }
    
}

modify01.Demo01

package com.shine.modify01;
​
public class Demo01 {
    public static void main(String[] args) {
        /**
         *  public
         *  protected
         *  default
         *  private
         */
        // 创建对象
        FFF fff = new FFF();
        
        /**
         *  同一个包中能访问:
         *      public
         *      protected
         *      default
         */
        System.out.println(fff.publicStr);
        System.out.println(fff.protectedStr);
        System.out.println(fff.defaultStr);
        // System.out.println(fff.privateStr);
    }
}

modify02.SSS

package com.shine.modify02;
​
import com.shine.modify01.FFF;
​
/**
 *  FFF的子类
 */
public class SSS extends FFF {
    
    /**
     *  在不同包子类中能访问的内容:
     *      public
     *      protected
     */
    public void show() {
        System.out.println(publicStr);
        System.out.println(protectedStr);
        // System.out.println(defaultStr);
        // System.out.println(privateStr);
    }
}

modify02.Demo02

package com.shine.modify02;
​
import com.shine.modify01.FFF;
​
public class Demo02 {
    public static void main(String[] args) {
        // 创建对象
        FFF fff = new FFF();
        
        /**
         *  同其他位置能访问:
         *      public
         */
        System.out.println(fff.publicStr);
        // System.out.println(fff.protectedStr);
        // System.out.println(fff.defaultStr);
        // System.out.println(fff.privateStr);
    }
}

四、方法重写

4.1 概述

  • 子类从父类中继承得到的方法不一定能满足需求

  • 可以在子类中定义和父类中【几乎】相同的方法:

    • 方法的声明部分相同
    • 方法体不同,可以根据子类需要重写方法体

4.2 重写注意事项

  • 重写可以使用override标注
  • 重写的方法参数列表、返回值类型必须和父类中相同
  • 重写方法的访问修饰符范围要大于等于父类方法的修饰符
  • 优先使用被重写的方法

4.3 代码

Worker

package com.shine.override;
​
/**
 *  类名
 *      工人
 *  方法
 *      工作
 */
public class Worker {
​
    void work() {
        System.out.println("工人需要工作");
    }
}

Cook

package com.shine.override;
​
/**
 *  类名
 *      厨师
 *      继承Worker,得到属性和方法
 */
public class Cook extends Worker{
    @Override
    void work() {
        System.out.println("厨师的工作是切墩和颠勺");
    }
}

Driver

package com.shine.override;
​
/**
 *  类名
 *      司机
 *      继承了Worker
 */
public class Driver extends Worker{
    
    @Override
    public void work() {
        System.out.println("司机的工作是开车");
    }
​
    public void work(String info) {
        System.out.println("司机的工作是" + info);
    }
    
}

TestWorker

package com.shine.override;
​
public class TestWorker {
    public static void main(String[] args) {
        // 工人对象
        Worker worker = new Worker();
        worker.work();
        
        // 厨师对象
        Cook cook = new Cook();
        // 使用子类重写之后的方法
        cook.work();
        
        // 司机对象
        Driver driver = new Driver();
        // 使用子类重写之后的方法
        driver.work();
    }
}

五、super

5.1 概述

  • 如果子类中存在和父类中重名的属性和方法

  • 子类中的属性和方法会屏蔽父类中的属性和方法

  • 如果明确表示调用父类中的属性和方法?

    • 使用super来明确表示调用父类中的内容

5.2 super的使用

调用父类中的属性

super.属性

调用父类中的方法

super.方法(参数)

调用父类中的构造器

super(参数)

父类

package com.shine.super0;
​
public class WeChatV1 {
    String name;
    String info;
    String version = "Version 1.0";
    
    public WeChatV1() {
        super();
    }
​
    public WeChatV1(String name, String info, String version) {
        super();
        this.name = name;
        this.info = info;
        this.version = version;
    }
​
    public void chat() {
        System.out.println("微信第一版,能使用流量发送免费文字信息");
    }
}

子类

package com.shine.super0;
​
public class WeChatV2 extends WeChatV1{
    String version = "Version 2.0";
    
    public WeChatV2() {
        this("", "", "");
    }
​
    public WeChatV2(String name, String info, String version) {
        super(name, info, version); // 调用父类中的构造方法,必须放在构造方法的第一行
    }
​
    @Override
    public void chat() {
        super.chat();   // 调用父类中的实例方法
        System.out.println("微信第2版,能发送图片和语音消息");
    }
    
    public void show() {
        // 输出子类和父类中的属性
        String version = "Version 2.1";
        System.out.println(version);        // 局部变量
        System.out.println(this.version);   // 实例变量
        System.out.println(super.version);  // 父类中的实例变量
    }
    
}

测试

package com.shine.super0;
​
public class Demo01 {
    public static void main(String[] args) {
        /**
         *  父类
         *      属性
         *      方法
         *      构造器
         *  子类
         *      属性
         *      方法
         *      构造器
         */
        
        WeChatV2 chatV2 = new WeChatV2();
        chatV2.chat();
    }
}

5.3 子类对象创建过程

  • 创建子类对象之前需要先创建父类对象

  • 有父类的属性和方法 + 子类的属性和方法,构成子类的对象

    • 默认调用父类的无参数构造方法,可以省略调用的代码

5.4 super调用构造器

调用无参数构造器

  • 在创建子类对象过程中默认调用父类中的无参数构造方法

调用有参数构造器

  • 如果父类中没有无参数构造方法,子类必须显示调