Java 面向对象入门

目标读者

了解 Java 基本数据类型
掌握 Java 输出、for、if 等基本语法
熟练应用函数,了解函数重载等基本知识
熟练使用 IntelliJ IDEA

权限修饰符

类、成员变量、成员方法最前面的单词叫做权限修饰符,表明从项目的哪些地方可以访问这个类、变量、方法。具体见下表:

是否能访问 同一文件 同一包 子类 不同类
public
protected
default(缺省)
private

举例:

类:老师(Teacher)

特征:成员变量:有姓名(name),年龄(age)等属性

行为:成员方法:讲课(teaching)、布置作业(assignWork)

Class(类)

语法规则:

// public class xxx
// xxx 自己给类取的名字
public class Teacher{
    
    // 成员变量
    String name;
    int age;
    
    // 构造方法 --- 获得对象的方法
    // 与类同名,无返回值
    // 在用该类实例化一个对象的时候需要被调用
    // 类默认自带无参构造函数
    Teacher(){
        
    }
    
    // 有参构造函数
    // 一般是为成员变量赋值
    Teacher(String name){
        ......
    }
    
    // 普通成员方法
    private void teaching(){
        ......
    }
    
    void assignWork(){
        ......
    }
}

思考:

1.teaching是否可以获得值 name 或者 age?

根据变量的作用域可知,是可以的。

举例:

有一个老师,她叫twter,年龄是18岁

有一个老师,她叫冠中,年龄是5岁

有一个老师,她叫昕姐,年龄是3岁

对象

对象是描述客观事物的一个实体,由类实例化来生成。

普通的成员变量和成员方法都是属于这个对象的。

即这个对象诞生,属于这个对象的成员变量和成员方法才诞生。

要通过对象才能获得成员变量和成员方法。

构造方法

构造方法是类与对象的桥梁,构造方法和类同名,且没有返回值。

在构造方法内可以进行成员变量的赋值。

通过new调用构造方法可以获得类的实例化对象。

public class Teacher {

    // 成员变量
    String name;
    int age;

    // 构造方法
    // 默认自带无参
    Teacher() {

    }
    
    Teacher(String mname,int mage){
        name = mname;
        age = mage;
    }
}

public class Test {
    public static void main(String[] args) {
        // 通过new可以生成一个新的具体的类
        // 我们称之为实例化 Teacher 生成一个 Teacher 的对象
        Teacher teacher = new Teacher();
        Teacher teacher1 = new Teacher();
        // teacher 和 teacher1 不是同一个对象
        teacher.name = "twter";
        teacher.age = 18;
        
        // 执行构造函数内的语句,进行赋值
        // Teacher的实例化对象 teacher3
        // teacher3的name是twter,age是18
        Teacher teacher2 = new Teacher("twter", 18);
        Teacher teacher3 = new Teacher("greenTea", 12);
    }
}

思考:

1.如何获得一个老师,她叫绿茶,年龄是12岁。

2.有参构造函数可以写成如下形式吗?

public class Teacher {

    // 成员变量
    String name;
    int age;
    
    Teacher(String name,int age){
        name = name;
        age = age;
    }
}

this

代表“当前对象”示例

就可以区别传入的参数“name”和对象自己的“name”。

public class Teacher {

    // 成员变量
    String name;
    int age;
    
    Teacher(String name,int age){
        this.name = name;
        this.age = age;
    }
}

举例:

某个老师上课(teaching)的时候会说 name 老师在上课

成员方法

public class Teacher {

    // 成员变量
    String name;
    int age;
    
    Teacher(String name){
        this.name = name;
    }
    
    Teacher(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 普通成员方法
    void teaching() {
        System.out.println(name + "is teaching");
    }
}


public class Test {
    public static void main(String[] args) {
        Teacher teacher2 = new Teacher("twter", 18);
        Teacher teacher3 = new Teacher("sxbasubx");
        
        teacher2.teaching();
    }
}

思考:

1.某个老师布置作业(assingWork)的时候会说老师布置了 x 道作业

public class Teacher {

    // 成员变量
    String name;
    int age;

    Teacher(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    void assignWork(int x) {
        System.out.println(name + " assign " + x + " number of homework");
    }
}

public class Test {
    public static void main(String[] args) {
        Teacher teacher2 = new Teacher("twter", 18);
        teacher2.assignWork(2);
    }
}

2.如何保护 name 不被随意修改?

public class Teacher {

    // 成员变量
    private String name;
}

但是我在main函数里想要获得老师对象的 name?

public class Teacher {

    // 成员变量
    private String name;
    
    public String getName() {
        return name;
    }
}

封装

要访问该类的代码和数据,必须通过严格的接口控制。

外部可以修改name,比如在main函数里可以修改name,但是必须按照规定的方式来。

public class Teacher {

    // 成员变量
    private String name;
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}

疑惑:那这和我直接用 public 修饰 name 变量有什么区别呐?

课堂作业

类:小饼干(cookie)

这个小饼干是由巧克力和抹茶组成的!

成员变量:价格(price),小饼干中巧克力的价格(priceOfChocolate),小饼干中抹茶的价格(priceOfTea)

price = priceOfChocolate + priceOfTea

我想要在main函数里实例化3个不同价格的巧克力和不同价格抹茶的组成的小饼干对象。

Coockie priceOfChocolate priceOfTea
coockie1 12.4 121
coockie2 13 423
Coockie3 12937 1213.2

根据 price 理解封装的好处。

想要统计生成的饼干数量?

这个信息应该是凌驾于对象上的

static

用static修饰的成员变量和成员方法不再依赖于对象,而是属于类本身。可以直接通过类名获得

1.静态方法里可以使用静态成员变量吗?

2.普通(非静态)方法里可以使用静态成员变量吗?

3.普通方法里可以使用普通成员变量吗?

4.静态方法里可以使用普通成员变量吗?

5.普通方法里可以调用静态方法吗?

6.静态方法里可以调用静态方法吗?

7.静态方法里可以调用普通方法吗?

yes yes yes no yes yes no

package xyz.chenshuyusc.course2;

public class Coockie {
    private double price;
    private double priceOfChocolate;
    private double priceOfTea;

    private static int count; // = 0

    public Coockie() {
        ++count;
    }

    public Coockie(double priceOfsth, boolean isTea) {
        if (isTea) {
            this.priceOfTea = priceOfsth;
        } else {
            this.priceOfChocolate = priceOfsth;
        }
        this.price = this.priceOfTea;
        ++count;
    }

    public Coockie(double priceOfTea){
        this.priceOfTea = priceOfTea;
        this.price = this.priceOfTea;
    }

    public double getPrice() {
        return price;
    }

    public double getPriceOfChocolate() {
        return priceOfChocolate;
    }

    public double getPriceOfTea() {
        return priceOfTea;
    }


    public void setPriceOfChocolate(double priceOfChocolate) {
        this.priceOfChocolate = priceOfChocolate;
        this.price = this.priceOfChocolate + this.priceOfTea;
    }

    public void setPriceOfTea(double priceOfTea) {
        this.priceOfTea = priceOfTea;
        this.price = this.priceOfChocolate + this.priceOfTea;
    }

    public static int getCount() {
        return count;
    }

    protected void setPrice(double price) {
        this.price = price;
    }
}

举例子:

类:甜甜的小饼干

这个小饼干是由巧克力和抹茶组成的甜味小饼干!

成员变量:价格(price),小饼干中巧克力的价格(priceOfChocolate),小饼干中抹茶的巧克(priceOfTea),糖(priceOfSugar)

类:咸咸的小饼干

这个小饼干是由巧克力和抹茶组成的咸味小饼干!

成员变量:价格(price),小饼干中巧克力的价格(priceOfChocolate),小饼干中抹茶的巧克(priceOfTea),盐(priceOfYan)

看起来和之前的小饼干很重合!!!

extends ( 继承 )

子类继承父类的特征和行为。

即甜甜的小饼干继承小饼干,就获得了小饼干中非private的成员变量和成员方法。

但甜甜的小饼干又比小饼干多了priceOfSugar。

public class Coockie {
    private double price;
    private double priceOfChocolate;
    private double priceOfTea;

    public Coockie() {
    }

    public Coockie(double priceOfsth, boolean isTea) {
        if (isTea) {
            this.priceOfTea = priceOfsth;
        } else {
            this.priceOfChocolate = priceOfsth;
        }
        this.price = this.priceOfTea;
    }

    public double getPrice() {
        return price;
    }

    public double getPriceOfChocolate() {
        return priceOfChocolate;
    }

    public double getPriceOfTea() {
        return priceOfTea;
    }


    public void setPriceOfChocolate(double priceOfChocolate) {
        this.priceOfChocolate = priceOfChocolate;
        this.price = this.priceOfChocolate + this.priceOfTea;
    }

    public void setPriceOfTea(double priceOfTea) {
        this.priceOfTea = priceOfTea;
        this.price = this.priceOfChocolate + this.priceOfTea;
    }

    protected void setPrice(double price) {
        this.price = price;
    }
}


public class SugarCoockie extends Coockie {
    private double priceOfSugar;

    public SugarCoockie(double priceOfsth, boolean isTea) {
        super(priceOfsth,isTea);
    }
    
    public double getPriceOfSugar() {
        return priceOfSugar;
    }

    public void setPriceOfSugar(double priceOfSugar) {
        setPrice(getPrice() - this.priceOfSugar + priceOfSugar);
        this.priceOfSugar = priceOfSugar;
    }
}

子类的构造方法必须调用父类的构造方法。

思考:如果要通过子类实例化对象,父类可以没有构造函数吗?

Override

子类中包含跟父类方法签名一样的方法,父类的方法会被覆盖掉,我们就说该方法被重写。如需调用父类原有的成员方法,可使用 super 关键字。

public class Coockie {
    protected double price;
    protected double priceOfChocolate;
    protected double priceOfTea;

    public Coockie() {
    }

    public Coockie(double priceOfsth, boolean isTea) {
        if (isTea) {
            this.priceOfTea = priceOfsth;
        } else {
            this.priceOfChocolate = priceOfsth;
        }
        this.price = this.priceOfTea;
    }

    public double getPrice() {
        return price;
    }

    public double getPriceOfChocolate() {
        return priceOfChocolate;
    }

    public double getPriceOfTea() {
        return priceOfTea;
    }


    public void setPriceOfChocolate(double priceOfChocolate) {
        this.priceOfChocolate = priceOfChocolate;
        this.price = this.priceOfChocolate + this.priceOfTea;
    }

    public void setPriceOfTea(double priceOfTea) {
        this.priceOfTea = priceOfTea;
        this.price = this.priceOfChocolate + this.priceOfTea;
    }

    public static int getCount() {
        return count;
    }

    protected void setPrice(double price) {
        this.price = price;
    }
}


public class SugarCoockie extends Coockie {
    private double priceOfSugar;

    @Override
    public void setPriceOfChocolate(double priceOfChocolate) {
        this.priceOfChocolate = priceOfChocolate;
        this.price = this.priceOfSugar + this.priceOfChocolate + this.priceOfTea;
    }

    @Override
    public void setPriceOfTea(double priceOfTea) {
        super.setPriceOfTea(priceOfTea);
        this.price = this.priceOfSugar + this.priceOfChocolate + this.priceOfTea;
    }

    public double getPriceOfSugar() {
        return priceOfSugar;
    }

    public void setPriceOfSugar(double priceOfSugar) {
        this.priceOfSugar = priceOfSugar;
        this.price = this.priceOfSugar + this.priceOfChocolate + this.priceOfTea;
    }

}

Builder 设计模式

当一个类需要初始化的成员变量比较多、比较复杂时,仅使用构造方法来初始化对象就显得冗余且难以理解,这里介绍一个经典的解决办法:利用 Builder 设计模式实现链式调用来获取对象。

package xyz.chenshuyusc.course2;

public class Coockie {
    double price;
    double priceOfChocolate;
    double priceOfTea;
    Choc choc = new Choc();

    public Coockie() {
    }

    public Coockie(double priceOfChocolate, double priceOfTea,Choc choc) {
        this.choc = choc;
        this.priceOfTea = priceOfTea;
        this.priceOfChocolate = priceOfChocolate;
        this.price = this.priceOfTea + this.priceOfChocolate;
    }
    
    public double getPrice() {
        return price;
    }

    public double getPriceOfChocolate() {
        return priceOfChocolate;
    }

    public double getPriceOfTea() {
        return priceOfTea;
    }


    public void setPriceOfChocolate(double priceOfChocolate) {
        choc.price = priceOfChocolate;
        this.priceOfChocolate = priceOfChocolate;
        this.price = this.priceOfChocolate + this.priceOfTea;
    }

    public void setPriceOfTea(double priceOfTea) {
        this.priceOfTea = priceOfTea;
        this.price = this.priceOfChocolate + this.priceOfTea;
    }

}

public class CoockieBuilder {

    private Coockie coockie = new Coockie();

    public CoockieBuilder priceOfTea(double priceOfTea) {
        coockie.setPriceOfTea(priceOfTea);
        return this;
    }

    public CoockieBuilder priceOfChocolate(double priceOfChocolate) {
        coockie.setPriceOfChocolate(priceOfChocolate);
        return this;
    }
}

package xyz.chenshuyusc.course2;

public class TestCoockie {
    public static void main(String[] args) {

        Coockie coockie = new CoockieBuilder()
                .priceOfChocolate(1213)
                .priceOfTea(1293)
                .build();

        CoockieBuilder coockieBuilder = new CoockieBuilder();
        coockieBuilder = coockieBuilder.priceOfTea(1231.2);
        coockieBuilder = coockieBuilder.priceOfChocolate(21);
        coockieBuilder = coockieBuilder.priceOfTea(213);


        System.out.println(coockie.getPriceOfChocolate());
        System.out.println(coockie.getPriceOfTea());
        System.out.println(coockie.getPrice());
    }
}

你可能感兴趣的:(Java 面向对象入门)