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());
    }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343