Java基础7

面向对象的特征一:封装性

随着我们系统越来越复杂,类会越来越多,那么类之间的访问边界必须把握好,面向对象的开发原则要遵循“高内聚、低耦合

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

低耦合:仅暴露少量的方法给外部使用,尽量方便外部调用。

何为封装性?

所谓封装性,就是把客观事物封装成抽象概念的类,并且类可以把自己的数据和方法只向可信的类或者对象开放,向没必要开放的类或对象隐藏信息。

权限修饰符

4种权限修饰符: private / 缺省 / protected / public

可以使用4种权限修饰符修饰类及类的内部成员。当这些成员被调用时,体现可见性的大小。

实际案例: 在题目中,我们给Animal的对象的legs属性赋值。在实际的常识中,我们知道legs不能赋值为负数的。到那会是如果直接调用属性legs没事不可以加入逻辑判断的,为了解决这个问题:

> 将legs属性私有化(private),禁止在Animal类的外部直接调用此属性

> 提供给legs属性赋值的setLegs()方法,在此方法中加入legs赋值的判断逻辑  if(l >= 0 && l % 2 == 0) 将此方法暴露出去,使得Animal类的外部调用此方法,对legs属性赋值。

> 提供给legs属性获取的getLegs()方法,此方法对外暴露。使得在Animal类的外部还可以调用此属性的值。

复制代码
public class AnimalTest {
    public static void main(String[] args){
        Animal animal1 = new Animal();
        animal1.name = "小兔";
        // animal1.legs = -4; 这里的赋值其实是不合理的,所以为了将这种不合理的赋值消灭 我们可以写一个赋值的方法,并取消这种.的赋值方法
        animal1.setLegs(4);
        // 那么相应的我们输出就不能写:
        // System.out.println(animal1.legs);   因为我们不能够.的方式调用  所以我们还需要一个获取legs值的方法
        System.out.println(animal1.getLegs());
        animal1.eat();
    }
}

class Animal{
    String name;
    private int legs; // 为了防止用户用.的方式去赋值legs

    public void eat(){
        System.out.println("动物觅食");
    }

    public void setLegs(int l){
        if(l >= 0 && l % 2 == 0){
            legs = l;
        }else{
            System.out.println("你输入的数据非法!");
        }
    }
    public int getLegs(){
        return legs;
    }
}
复制代码

权限修饰符的范围

 类: 只能使用public / 缺省 修饰

类的内部成员: 可以使用4种权限修饰

封装性的体现

> 场景1: 私有化(private)类的属性,提供公共(public)的get和set方法,对此属性进行获取或修改

> 场景2: 将类中不需要对外暴露的方法,设置为 private

> 场景3: 单例模式中构造器private(私有)的了,避免在类的外部创建实例。

 构造器

作用1:搭配new关键字,创建类的对象。

作用2:在创建对象的同时,可以给对象的相关属性赋值

格式: 权限修饰符 类名(形参列表){ }

注意: 创建类以后,在没有显示提供任何构造器的情况下,系统会默认提供一个空参的构造器,且构造器的权限与类声明的权限相同。

    一旦类中显示声明了构造器,则系统不再提供默认的空参的构造器。

复制代码
public class Student {
    String name;
    int age;
    String school;
    String major;
    /*
     *与类名一致的方法名
     * 构造方法是在创建对象的时候调用
     * 类在没有定义构造方法的时候有一个默认的无参构造
     * 初始化成员变量
     */
    public Student (String n, int a){
        name = n;
        age = a;
    }
    public Student (String n, int a, String s){
        name = n;
        age = a;
        school = s;
    }
    public Student (String n, int a, String s, String m){
        name = n;
        age = a;
        school = s;
        major = m;
    }
    public String getInfo(){
        return "name = " + name + ",age = " + age + ",school = " + school + ",major = " + major;
    }
}

public class StudentDemo {
    public static void main(String[] args){
        Student s=new Student("小明", 19);
        System.out.println(s.age);
        System.out.println(s.getInfo());
    }
}
复制代码

属性赋值过程

在类的属性中,有哪些位置给属性赋值:

① 默认初始化;

② 显式初始化;

③ 构造器中初始化;

④ 通过“对象.方法”的方式赋值;

⑤ 通过“对象.属性”的方式赋值;

执行的先后顺序: ① - ② - ③ - ④ / ⑤

以上操作在对象创建过程中可以执行的次数如何:  

> 只能执行一次: ①、②、③

> 可以多次执行: ④、⑤ 

JavaBean

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

好比做了一个扳手,这个扳手会在很多地方被拿去用。这个扳手也提供多种功能(可以拿这个扳手扳、锤、撬等),而这个扳手就是一个组件。

所谓JavaBean,是符合如下标准的java类:

① 类是公共的     ② 有一个无参的公共的构造器     ③ 有属性,且有对应的get、set方法

UML类图

常用的UML工具软件有 PowerDesinger、RoseEnterprise Architect

UML工具软件不仅可以绘制软件开发中所需的各种图表,还可以生成对应的源代码。

在软件开发中,使用UML类图可以更加直观地描述类内部结构(类的属性和操作)以及类之间的关系(如关联、依赖、聚合等)

  • + 表示public类型, - 表示private类型, # 表示protected类型
  • 方法的写法:  方法的类型(+、-) 方法名(参数名:参数类型):返回值类型
  • 斜体表示抽象方法或类

 

this关键字

目前出现的问题:

声明的一个属性对应的setXXX方法时,通过形参给对应的属性赋值。如果形参名和和属性名同名了,那么该如何在方法内区分这两个变量

解决方案: 使用this。具体来讲,使用this修饰的变量,表示的是属性。没有使用this修饰的,表示的是形参

this功能

可以调用:成员变量、方法、构造器

this一般理解为 当前对象(在方法中调用时) 或 正在创建的对象 (在构造器中调用时)

复制代码
public class Boy {
    private String name;
    private int age;
    public Boy(String name, int 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 marry(Girl girl){
        System.out.println("我想娶" + girl.getName());
    }
    public void shout(){

    }
}
复制代码
复制代码
public class Girl {
    private String name;
    private int age;
    public Girl(String name, int age){
        this.name = name;
        this.age = age;
    }
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
    public void marry(Boy boy) {
        System.out.println("我想嫁给" + boy.getName());
        boy.marry(this);  //调用boy的marry,并使用this关键字把当前的女孩对象传入  得到的就是当前女孩的名字
    }
    public int compare(Girl girl){  //比较两个对象的年龄大小
        if (this.age > girl.age){
            return 1;
        }else if (this.age < girl.age){
            return -1;
        }else{
            return 0;
        }
    }
}
复制代码
复制代码
public class Test {
    public static void main(String[] args){
        Boy boy1 = new Boy("杰克",23);
        Girl girl1 = new Girl("朱丽叶",21);
        girl1.marry(boy1);
        Girl girl2 = new Girl("rose",19);
        int compare = girl1.compare(girl2);
        if(compare > 0){
            System.out.println(girl1.getName() + "大");
        }else if(compare < 0){
            System.out.println(girl2.getName() + "大");
        }else {
            System.out.println("一样大");
        }
    }
}
复制代码

this调用属性和方法

  • 针对于方法内的使用情况:(准确的说是非static修饰的方法)

一般情况:通过对象a调用方法,可以在方法内调用当前对象a的属性或其他方法。此时,我们可以在属性和其他方法前使用“this”,表示当前属性或方法所属的对象。但是一般情况下,我们都选择省略此“this”结构

特殊情况:如果方法的形参与对象的属性同名了,我们必须使用“this.”进行区分。使用this.修饰的变量即为属性(或成员变量),没有使用this.修饰的即为局部变量。

  • 针对于构造器内的使用情况:

一般情况:通过构造器创建对象时,可以在构造器内调用当前正在创建的对象的属性或方法。此时,我们可以在属性和方法前使用“this”,表示当前属性或方法所属的对象。但是一般情况下,我们都选择省略此“this”结构

特殊情况:如果构造器的形参与正在创建的对象的属性同名了,我们必须使用“this.”进行区分。使用this.修饰的变量即为属性(或成员变量),没有使用this.修饰的即为局部变量。

复制代码
public class PersonTest {
    public static void main(String[] args){
        Person p1 = new Person("Tom","tom@126.com");
        p1.setAge(10);
    }
}

class Person{
    String name;
    int age;
    String email;

    public  Person(String name, String email){  //构造器
        this.name = name;
        this.email = email;
    }

    public void setAge(int age){  //这里为了见名知意 最好还是把变量名设置为age
        this.age = age;
    }
    public int getAge(){
        return this.age;
    }
}
复制代码

this调用构造器

我们可以在类的构造器中调用当前类中指定的其它构造器。

格式: this(形式参数)

要求:this(形参列表)必须声明在当前构造器的首行

结论:this(形参列表)在构造器中最多声明一个     如果一个类中声明了n个构造器,则最多有n-1个构造器可以声明有this(形参列表)的结构  不要形成环相互调用

复制代码
public class PersonTest {
    public static void main(String[] args){
        //虽然构造器里面用this调用了构造器,但是只new了一个对象 所以只创建了1个Person类对象
        Person p1 = new Person(16);
    }
}

class Person{
    String name;
    int age;
    String email;

    public Person(){
        //
    }
    public Person(int age){
        this(); //这里调用的就是上面的空参的构造器
        this.age = age;
    }
    public  Person(String name, String email){  //构造器
        this.name = name;
        this.email = email;
    }

}
复制代码

例子:

复制代码
public class Account {
    private double balance;

    public Account(double balance){
        this.balance = balance;
    }
    public double getBalance(){
        return balance;
    }
    public void deposit(double amt){
        if(amt > 0 && balance >- amt){
            balance -= amt;
            System.out.println("成功取出" + amt);
        }else {
            System.out.println("取款数额有误或者余额不足!");
        }
    }
    public void withdraw(double amt){
        if (amt > 0){
            balance += amt;
            System.out.println("成功存入" + amt);
        }
    }
}
复制代码
复制代码
public class Customer {
    String firstName;
    String lastName;
    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 acct){
        account = acct;
    }
}
复制代码
复制代码
public class Bank {
    private Customer[] customers; //保存多个客户
    private int numberOfCustomer;  //存储的 客户个数

    public Bank(){
        customers = new Customer[10];
    }
    public void addCustomer(String f, String l){
        Customer c = new Customer(f,l);
        customers[numberOfCustomer] = c;
        numberOfCustomer++;
    }
    public int getNumberOfCustomer(){
        return numberOfCustomer;
    }
    public Customer getCustomer(int index){
        if(index < 0 || index >= numberOfCustomer){
            return null;
        }else{
            return customers[index];
        }
    }
}
复制代码
复制代码
public class Test {
    public static void main(String[] args){
        Bank bank = new Bank();
        bank.addCustomer("明", "小");
        bank.addCustomer("红", "小");
        bank.getCustomer(0).setAccount(new Account(3000));
        bank.getCustomer(0).getAccount().withdraw(60);
        System.out.println("账户余额:" + bank.getCustomer(0).getAccount().getBalance());
    }
}
复制代码

 

posted on   gjwqz  阅读(6)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示