【Java自学】搬砖中年人代码自学之路Lesson 8

在Java自学过程中, Lesson 8 主要讲解了封装性原理,强调了高内聚、低耦合的设计思想,并通过实例解释了如何通过权限修饰符实现封装。此外,还介绍了构造器的作用和重载,以及this关键字的使用场景,包括在构造器中调用其他构造器的规则。最后提到了JavaBean的标准和作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


这一堂课听的最多的一句话就是「这部分先了解就可以,后面到了xxx的时候会深入的讲」,就给人一种后面还有茫茫多的只是要学习一样。。。。

不过今天学的这些东西自己倒是能听懂,唯独就是后面的练习题,在各种点来点去的时候,会搞不清楚测试的顺序,创建类什么的都已经ok了,但是就是在使用调用的时候会受忙脚乱,不知道该怎么调用,或者说不知道该调用谁再调用谁,这个估计后面还得多练练才能搞清楚,脑子慢真心伤不起

在就是免费课确实没有付费课香,这么多的资料全都得自己手动敲下来,而不是像人家一样直接点开文件夹拿出报名时候给到的压缩包就好,这个还是比较不爽的。但是这段时间敲英文字的水平确实是有进步,打字快了好多,而且确实还挺快乐的。但是学会了eclipse里面的快速创建构造器、setter和getter的快捷方式的时候,瞬间感觉打字不香了。


🇺🇳        封装性——"我要用洗衣机,只需要按一下开关和洗涤模式就可以了,有必要了解洗衣机内部的结构么?有必要碰电动机么?"

一、我们程序涉及追求"高内聚,低耦合"

> 高内聚:类的内部数据操作细节自己完成,不允许外部干涉

> 低耦合:仅对外暴露少量的方法用于使用

二、隐藏对象内部的复杂性,只对外公开简单的接口,便于外界调用,从而提高系统的可扩展性、可维护性。

        通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想

三、面向对象的特征一:封装与隐藏

        1、问题的引入

                > 当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值。

                   这里,赋值操作要受到属性的数据类型和存储范围的制约,除此之外,没有其他制约条件

                   但是,在实际问题中,我们往往需要给属性赋值加入额外的限制条件,这个限制条件就不能在属性声明时体现,

                   只能通过方法进行限制条件的添加(比如下面写的setLegs())

                   同时,我们需要避免用户再使用"对象.属性"的方式对属性进行赋值,则需要将属性声明为私有的(private)

                   此时,针对属性就体现了封装性

public class AnimalTest{
    public static void main(String[] args){
        Animal test = new Animal();
        test.name = "大黄";
        test.setLegs(6);
        test.show();
    }
}
class Animal{
    String name;
    private int age;
    private int legs;

    //对于属性的设置
    public void setLegs(int l){
        if(l >= 0 && l % 2 ==0){
            legs = l;
        }else{
            legs = 0;
        }
    }

    //对于属性的获取
    public int getLegs(){
        return legs;
    }

    public void eat(){
        System.out.println("动物进食");
    }
    public void show(){
        System.out.println("name = " + name + ",age = " + age + ",legs = " + legs);
    }
}

                        > 属性赋值的先后顺序

                                > 默认初始化值

                                > 显式初始化

                                > 构造器中初始化

                                ⬆️上面三个操作只执行一次

                                > 通过"对象.set方法"或者"对象.属性"的方式进行赋值

                                ⬆️这条操作是可以反复执行的

                                以上操作的先后顺序: 1 - 2 - 3 - 4

public class UserTest{
    public static void main(String[] args){
        User u = new User();
        System.out.println(u.age);

        User u1 = new User(2);
        u1.setAge(3);
        System.out.println(u1.age);
    }
}
class User{
    String name;
    int age;

    public User(){

    }
    public User(int a){
        age = a;
    }
    
    public void setAge(int a){
        age = a;
    }
}

        2、封装性的体现:

                > 我们将类的属性私有化(private),同时,提供公共的(public)方法来获取(getXxx)和设置(setXxx)此属性的值

//【练习】
//创建程序,在其中定义两个类:Person和PersonTest类。定义如下:
//用setAge()设置人的合法年龄(0-130),用getAge()返回人的年龄。
//在PersonTest类种实力话Person类的对象b,调用setAge()和getAge()方法,体会Java的封装性

//Person

//-age:int

//+setAge(i:int)
//+getAge();int

public class PersonTest{
    public static void main(String[] args){
        Person b = new Person();
        b.setAge(5);
        b.getAge();
    }
}
class Person{
    private int age;

    public void setAge(int i){
        age = i;
    }
    public int getAge(){
        return age;
    }
}

        3、拓展——封装性的体现:

                > 如上

                > 不对外暴露的私有的方法

                > 单例模式(构造器部分讲解)

                > ...

        4、封装性的体现,需要权限修饰符来进行配合

                > Java规定的4种权限(从小到大排列):private缺省(英文会写作default,但是其实写上就报错了,所以缺省意味着什么都不用写)、protectedpublic

                   置于类的成员定义前,用来限定对象对该类成员的访问权限   

        > 全部4种权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类

        > 只有2种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类

                > 对于class的权限修饰只可以用public和default(缺省)

                        > public类可以在任意地方被访问

                        > default类只可以被同一个包内部的类访问

        > 总结封装性:Java提供了4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小

🇺🇳        构造器

类的结构之三:构造器(或构造方法:constructor,虽然也可以叫做构造方法,但是不能错误的认为构造器就是特殊的方法,格式跟方法不完全一样是一方面,最主要的一方面是功能不一样)的使用——任何一个类都有构造器

类的构成(属性「Field」、方法「Method」、构造器「Constructor」)

一、构造器的作用

        > 创建对象

        > 初始化对象的信息

二、说明

        > 如果没有显示的定义类的构造器的话,则系统默认提供一个空参的构造器 ==> 权限与类相同

        > 定义构造器的格式:权限修饰符 类名(形参列表){}

        > 一个类中定义的多个构造器,彼此构成重载

        > 一旦我们显示的定义了类的构造器之后,系统就不再提供默认的空参构造器了

                > 举例:家庭没有劳动力的时候,国家会给扶贫补贴,但是一旦家庭中有一个劳动力了,则国家不给扶贫补贴

        > 一个类中,至少要有一个构造器:可能是系统提供的空参构造器,也可能是自己定义的构造器

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

    }
}
class People{
    //属性
    String name;
    int age;

    //构造器
    public People(){
        System.out.println("People()......");
    }
    public People(String n){
        name = n;
    }
    public People(String n, int a){
        name = n;
        age = a;
    }

    //方法
    public void eat(){
        System.out.println("人吃饭");
    }
    public void study(){
        System.out.println("人可以学习");
    }
}
//【练习】
//编写两个类,TriAngle和TriAngleTest,其中,TriAngle类中声明私有的底边长base和高height
//同时声明公共方法访问私有变量
//此外,提供类必要的构造器
//另一个类中使用这些公共方法,计算三角形的面积

public class TriAngleTest{
    public static void main(String[] args){
        TriAngle test = new TriAngle();
        test.setBase(2.0);
        test.setHeight(2.4);
        System.out.println("base : " + test.getBase() + ",height : " + test.getHeight());
        
        TriAngle test2 = new TriAngle();
        System.out.println("base : " + test2.getBase() + ",height : " + test2.getHeight());
    }
}
class TriAngle{
    private double base;
    private double height;

    public TriAngle(){

    }
    public TriAngle(double a,double b){
        base = a;
        height = b;
    }

    public void setBase(double b){
        base = b;
    }
    public void setHeight(double h){
        height = h;
    }
    public double getBase(){
        return base;
    }
    public double getHeight(){
        return height;
    }
    public double findArea(){
        return base * height * 0.5;
    }
}

🇺🇳        this关键字的使用

> 在Java中,this关键字比较难理解,它的作用和其词义很接近

> 它在方法内部使用,即这个方法所属对象的引用

        > 可以使用"this.属性"或者"this.方法"的方式,调用当前对象属性或方法,但是通常情况下,选择省略"this."

        > 特殊情况下,如果方法的形参和类的属性同名时,必须显式的使用"this.变量"的方式表明此变量是属性,而非形参

> 它在构造器内部使用,表示该构造器正在初始化的对象

        > 可以使用"this.属性"或者"this.方法"的方式,调用当前正在创建的对象属性或方法,但是通常情况下,选择省略"this."

        > 特殊情况下,如果构造器的形参和类的属性同名时,必须显式的使用"this.变量"的方式表明此变量是属性,而非形参

> this表示当前对象,可以调用类的属性、方法和构造器

        > this理解为:当前对象

> this调用构造器

        > 我们在类的构造器中,可以显式的使用"this(形参列表)"的方式,调用本类中指定的其他构造器

           而且不管调用了多少个本类的其他构造器,其实结果就是只创建了一个对象

        > 构造器中不能通过"this(形参列表)"的方式调用自己

        > 如果一个类中有n个构造器,则最多有n-1个构造器中使用了"this(形参列表)"的方式

        > 【规定】"this(形参列表)"的方式调用其他构造器,必须声明在当前构造器的首行,如果不是首行,就会报错

           「Constructor call must be the first statement in a constructor」

        > 构造器内部,最多只能声明一个"this(形参列表)"的方式,用来调用其他的构造器

> 什么时候使用this关键字?

        > 当在方法内需要用到调用该方法的对象时,就用this

           具体的:我们课用this来区分局部变量和属性

           例如:this.name= name;

public class ThisTest{
    public static void main(String[] args){
        Person p1 = new Person();
        p1.setAge(1);
        System.out.println(p1.getAge());

        p1.eat();

        Person p2 = new Person("Jerry",20);
        System.out.println(p2.getAge());
    }
}
class Person{
    private String name;
    private int age;

    public Person(){
        String info = "此处省略40条代码";
        System.out.println(info);
    }
    public Person(String name){
        this();//表明调用上方的空参构造器
        this.name = name;
    }
    public Person(int age){
        this();
        this.age = age;
    }
    public Person(String name, int age){
        this(age);//表示调用上面这个(int age)的构造器,此时,本构造器中的age会直接赋值给上一个构造器的形参,所以下面的"this.age = 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 void eat(){
        System.out.println("人吃饭");
        study();//其实前面省略了一个"this."
    }
    public void study(){
        System.out.println("人学习");
    }
}

⚠️        JavaBean是一种Java语言写成的可重用组件

JavaBean是符合以下标准的Java类

        > 类是公共的

        > 有一个无参的公共的构造器

        > 有属性,且有对应的get,set方法

        用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以用Java代码创造的对象进行打包

        并且其他的开发者可以通过内部的JSP页面、servlet、其他的JavaBean、applet程序或者应用来使用这些对象

        用户可以认为JavaBean提供来一种随时随地的复制和粘贴的功能,而不用关心任何改变

两道练习题

//> 写一个名为Account的类模拟账户。该类的属性和方法如下所示。
//    > 该类包括属性:
//        > 账号id,余额balance,年利率annualInterestRate
//    > 该类包括方法:
//        > 访问器方法(getter和setter方法),取款方法withdraw(),存款方法deposit()
 
//    Account

//    private int id
//    private double balance
//    private double annualInterestRate

//    public Account(int id,double balance,double annualInterestRate)

//    public int getId()
//    public double getBalance()
//    public double getAnnualInterestRate()
//    public void setId(int id)
//    public void setBalance(double balance)
//    public void setAnnualInterestRate(double annualInterestRate)
//    public void withdraw(double amount)//取钱
//    public void deposit(double amount)//存钱

//    提示:在提款方法withdraw中,需要判断用户余额是否能够满足提款数额的要求,如果不能,应该出提示

//    > 创建Customer类
//    Customer

//    private String firstName
//    private String lastName
//    private Account account

//    public Customer(String f,String l)

//    public String getFirstName()
//    public String getLastName()
//    public Account getAccount()
//    public void setAccount(Account account)

//    a.声明三个私有对象属性:firstName、lastName和account
//    b.声明一个公有构造器,这个构造器带有两个代表对象属性的参数(f和l)
//    c.声明两个公有存取器来访问该对象属性,方法getFirstName和getLastName返回相应的属性
//    d.声明setAccount方法来对account属性赋值
//    e.声明getAccount方法来获取account属性

//    > 写一个测试程序
//        > 创建一个Customer,名字叫Jane Smith,他有个账号为1000,余额为2000元,年利率为1.23%的账户
//    > 对Jane Smith操作
//        > 存入100元,再取出960元,再取出2000元
//        > 打印出Jane Smith对基本信息

public class AccountCustomer{
    public static void main(String[] args){
        Customer c = new Customer("Jane","Smith");
        Account a = new Account(1000,2000,0.0123);
        c.getAccount().deposit(100);
        c.getAccount().withdraw(960);
        c.getAccount().withdraw(2000);

        System.out.println("Customer [" + cust.getLastName() + "," + cust.getFirstName() + "] has an account: id is " + cust.getAccount().getId() + ", annualInterestRate is " + cust.getAccount().getAnnualInterestRate() * 100 + "%, balance is " + cust.getAccount().getBalance());
    }
}
class Account{
    private int id;
    private double balance;
    private double annualInterestRate;

    public Account(int id, double balance, double annualInterestRate){

    }

    public int getId(){
        return id;
    }
    public double getBalance(){
        return balance;
    }
    public double getAnnualInterestRate(){
        return annualInterestRate;
    }
    public void setId(int id){
        this.id = id;
    }
    public void setBalance(double balance){
        this.balance = balance;
    }
    public void setAnnualInterestRate(double annualInterestRate){
        this. annualInterestRate = annualInterestRate;
    }
    public void withdraw(double amount){
        if(amount > balance){
            System.out.println("余额不足,取款失败");
            return;
        }
        balance -= amount;
        System.out.println("取款成功,取出:" + amount + "元");
    }
    public void deposits(double amount){
        if(amount > 0){
            balance += amount;
        }
        System.out.println("存款成功,存入:" + amount + "元");
    }
}
class Customer{
    private String firstName;
    private String lastName;
    private Account account;

    public Customer(String firstName,String lastName){
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    public String getFirstName(){
        return firstName;
    }
    public String getLastName(){
        return lastName;
    }
    public Account getAccount(){
        return account;
    }
    public void setAccount(Account account){
        this.account = account;
    }
}
//> 按照如下图的UML类图,创建相应的类,提供必要的结构
//Account

//-balance:double

//+Account(init_balance):double
//+getBalance():double
//+deposit(amt:double)
//+withdraw(amt:double)
//    > 在提款方法withdraw()中,需要判断用户余额是否能够满足提款数额的要求,如果不能,应该给出提示。deposit()方法表示存款

//> 按照如下图的UML类图,创建相应的类,提供必要的结构
//Customer

//-firstName:String
//-lastName:String
//-account:Account

//+Customer(f:String,l:String)

//+getFirstName():String
//+getLastName():String
//+getAccount():Account
//+setAccount(acct:Account)

//> 按照如下图的UML类图,创建相应的类,提供必要的结构
//Bank

//-customers:Customer[]
//-numberOfCustomer:int

//+Bank()
//+addCustomer(f:String,l:String)
//+getNumberOfCustomer();int
//+getCustomer(index:int):Customer

//    > addCustomer方法必须依照参数(姓,名)构造一个新的Customer对象,然后把它放啊都customer数组中,还必须把numberOfCustomer属性值+1
//    > getNumberOfCustomer方法返回numberOfCustomer属性值
//    > getCustomer方法返回与给出的index参数相关的客户

//> 创建BankTest类进行测试

public class AccountCustomerBank{
    public static void main(String[] args){
        Bank bank = new Bank();
        bank.addCustomer("Jane","Smith");
        bank.getCustomer(0).setAccount(new Account(2000));
        bank.getCustomer(0).getAccount().withdraw(500);
        double balance = bank.getCustomer(0).getAccount().getBalance();
        System.out.println("客户:" + bank.getCustomer(0).getFirstName() + " 的账户余额为:" + balance);
        bank.addCustomer("三", "张");
        System.out.println("银行客户的数量为:" + bank.getNumberOfCustomers());
    }
}
class Account{
    private double balance;

    public Account(double init_balance){
        this.balance = init_balance;
    }
    
    public double getBalance(){
        return balance;
    }
    public double deposit(double amount){
        if(amount > 0){
            balance += amount;
        }
        System.out.println("存款成功,存入:" + amount + "元");
    }
    public void withdraw(double amount){
        if(amount > balance){
            System.out.println("余额不足,取款失败");
            return;
        }
        balance -= amount;
        System.out.println("取款成功,取出:" + amount + "元");
    }
}
class Customer{
    private String firstName;
    private String lastName;
    private Account account;

    public Customer(String firstName,String lastName){
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    public String getFirstName(){
        return firstName;
    }
    public String getLastName(){
        return lastName;
    }
    public Account getAccount(){
        return account;
    }
    public void setAccount(Account account){
        this.account = account;
    }
}
class Bank{
    private Customer[] customers;
    private int numberOfCustomer;

    public Bank(){
        customers = new Customer[10];
    }
    public void addCustomer(String firstName,String lastName){
        Customer c = new Customer(firstName,lastName);
        customers[numberOfCustomer] = c;
        numberOfCustomer++;
    }
    public int getNumberOfCustomer(){
        return numberOfCustomer;
    }
    public Customer getCustomer(int index){
        if(index >= 0 && index < numberOfCustomer){
            return customers[index];
        }
        return null;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值