封装

概述:面向对象编程语言是对客观世界的模拟,客观世界里成员变量都是隐藏在对象内部的,外部无法直接操作和修改。封装可以认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。 要访问该类的数据,必须通过指定的 方式。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。

原则: 将属性隐藏起来,若需要访问某个属性,提供公共方法对其访问。

封装步骤:
1、使用 private 关键字来修饰成员变量。
2.、对需要访问的成员变量,提供对应的一对 getXxx 方法 、 setXxx 方法。

封装的操作—private关键字

private关键字含义:
1. private是一个权限修饰符,代表最小权限。
2. 可以修饰成员变量和成员方法。
3. 被private修饰后的成员变量和成员方法,只在本类中才能访问。
示例:

  1. package array;
  2. public class Method {
  3. private String name; //private修饰的成员变量
  4. private int age;
  5. private double score;
  6. public void setName(String a) {
  7. String name = "langlang";
  8. }
  9. public String getName() {
  10. return name;
  11. }
  12. public void setAge(int b) {
  13. int age = 12;
  14. }
  15. public int getAge() {
  16. return age;
  17. }
  18. }

封装优化1—this关键字

this的含义:代表所在类的当前对象的引用(地址值),即对象自己的引用。
铭记: 方法被哪个对象调用,方法中的this就代表哪个对象。即谁在调用,this就代表谁。

格式

  1. this.成员变量名;
  1. package array;
  2. public class Students {
  3. private String name; //private修饰的成员变量
  4. private int age;
  5. private double score;
  6. public void setName(String name) {
  7. this.name=name;
  8. }
  9. public String getName() {
  10. return name;
  11. }
  12. public void setAge(int age) {
  13. this.age = age;
  14. }
  15. public int getAge() {
  16. return age;
  17. }
  18. }

调用方法,输出结果

  1. package array;
  2. public class Test_1 {
  3. public static void main(String[] args){
  4. Students lll= new Students(); //构造一个新的方法lll代替另一个类Students;
  5. lll.setName("langyongling"); //setName方法里变量赋值
  6. System.out.println(lll.getName());
  7. lll.setAge(12);
  8. System.out.println(lll.getAge());
  9. }
  10. }

封装优化2—构造方法

作用:构造方法用来初始化一个新建的对象,给对象的成员变量赋初始值。

格式:

  1. 修饰符 构造方法名(参数列表){
  2. // 方法体
  3. }

示例:

  1. package array;
  2. public class Students {
  3. private String name; //private修饰的成员变量
  4. private int age;
  5. private double score;
  6. public Students(){ //无参构造方法
  7. }
  8. public Students(String namme,int age){ //有参构造方法,且是方法的重载
  9. this.name=name;
  10. this.age=age;
  11. this.score=score;
  12. }
  13. }

javabean
1、JavaBean 是 Java语言编写类的一种标准规范。
2、符合 JavaBean 的类,要求类必须是具体的和公共的,并且具有无 参数的构造方法,提供用来操作成员变量的 set 和 get 方法。

示例:符合JavaBean的类

  1. package array;
  2. public class Students {
  3. private String name; //private修饰的成员变量
  4. private int age;
  5. private double score;
  6. public Students() { //无参构造方法
  7. }
  8. public Students(String namme, int age) { //有参构造方法,且是方法的重载
  9. this.name = name;
  10. this.age = age;
  11. this.score = score;
  12. }
  13. public void setName(String name) {
  14. this.name = name;
  15. }
  16. public String getName() {
  17. return name;
  18. }
  19. public void setAge(int age) {
  20. this.age = age;
  21. }
  22. public int getAge() {
  23. return age;
  24. }
  25. }

继承

基础知识

定义: 就是子类继承父类的属性行为,使得子类对象具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。

优点:
1. 提高代码的复用性。
2. 类与类之间产生了关系,是多态的前提。

格式:

  1. class Father{
  2. //方法体;
  3. }
  4. class Son extends Father{
  5. //方法体;
  6. }

示例:

  1. //父类
  2. package moreclass;
  3. public class Father {
  4. String name ;
  5. int age;
  6. public void getName(){
  7. System.out.println("name"+":"+name);
  8. }
  9. public void getAge(){
  10. System.out.println("age"+":"+age);
  11. }
  12. }
  13. //子类继承父类
  14. package moreclass;
  15. public class Son extends Father {
  16. String sex;
  17. public void sex() {
  18. System.out.println("sex" + ":" + sex);
  19. }
  20. }
  21. //实例化对象
  22. package moreclass;
  23. public class GetName {
  24. public static void main(String[] args) {
  25. Son s = new Son();
  26. s.name="langyongling";
  27. s.sex="女";
  28. s.age=12;
  29. s.getName();
  30. s.getAge();
  31. s.sex();
  32. }
  33. }

结果:
image.png

继承后的特点——成员变量

1、成员变量不重名(参照上面示例)
相互之间不影响,并正确输出结果。
2、成员变量重名

  1. package moreclass;
  2. public class Father {
  3. String name ;
  4. int age;
  5. public void age(){
  6. System.out.println(age);
  7. }
  8. }
  9. package moreclass;
  10. public class Son extends Father {
  11. String name;
  12. public void sameName() {
  13. System.out.println("name" + ":" + this.name);
  14. System.out.println("name" + ":" + super.name);
  15. }
  16. }
  17. package moreclass;
  18. public class GetName {
  19. public static void main(String[] args) {
  20. Son s = new Son();
  21. Father f = new Father();
  22. s.name="langyongling";
  23. f.name="wangbin";
  24. s.age=11;
  25. s.sameName();
  26. s.age();
  27. }
  28. }

1、成员方法重名—重写(override)
定义:子类中出现和父类相同的方法名,传参类型和数量,会出现覆盖效果,称为方法的重写,声明不变,重新实现前提条件:方法在两个不同的类中,且这两个类之间有继承关系
示例:

  1. package moreclass;
  2. public class Father {
  3. String name;
  4. int age;
  5. public void name() {
  6. String name = "wangbin";
  7. System.out.println(name);
  8. }
  9. public void age(int a) {
  10. System.out.println(age);
  11. }
  12. }
  13. //子类
  14. package moreclass;
  15. public class Son extends Father {
  16. String name;
  17. public void name(){
  18. String name1="langlang";
  19. String name2="xiaokeai";
  20. System.out.println(name1);
  21. System.out.println(name2);
  22. }
  23. }
  24. //调用方法,运行结果
  25. package moreclass;
  26. public class GetName {
  27. public static void main(String[] args) {
  28. Son s = new Son();
  29. s.name();
  30. }
  31. }

结果:
image.png
说明:子类和父类都有相同的方法name(),属于方法的重写。子类方法覆盖父类方法,所以调用运行的结果是子类方法的运行结果。

继承后的特点——构造方法

  1. 构造方法的名字是与类名一致的。所以子类是无法继承父类构造方法的。
    2. 构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个 super() 表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。
    父类构造方法示例:
    1. public class Father {
    2. String name;
    3. int age;
    4. Father(){
    5. System.out.println("hahah");
    6. }
    7. }
    子类调用父类的构造方法: ```java package moreclass;

public class Son extends Father { String name; Son() { super(); //子类调用父类的构造方法 System.out.println(“wwooeo”); }

}

public class GetName { public static void main(String[] args) { Son s = new Son(); //实例化对象 } }

  1. 运行结果:<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21882085/1625410376144-fcdf738f-ee6b-44a5-b2e2-18b4b2092fbe.png#clientId=u2b2c0eac-abf5-4&from=paste&height=163&id=u6fbb2717&margin=%5Bobject%20Object%5D&name=image.png&originHeight=163&originWidth=890&originalType=binary&ratio=1&size=12498&status=done&style=none&taskId=uea6903d1-7913-4441-a11c-316dec2be9d&width=890)
  2. <a name="oKNDW"></a>
  3. #### super和this
  4. super:代表父类的存储空间标识(父类的引用)<br />this:代表当前对象的引用<br />用法<br />1、访问成员
  5. ```java
  6. this.成员变量 //当前类
  7. super.成员变量 //父类
  8. this.方法名() //当前类
  9. super.方法名() //父类

示例:

public class Father {
    String name;
    String sex;
    public void sex() {
        String sex="男";
        System.out.println(sex);
    }
}

//子类
public class Son extends Father {
    String sex;
    public void sex(){
        String sex="女";
        System.out.println(sex);
    }
    public void sex1(){
        this.sex();       //调用当前类方法
       super.sex();       //调用父类方法
    }
}


//调用方法
public class GetName {
    public static void main(String[] args) {
        Son s = new Son();
        s.sex1();
    }
}

结果:
image.png

继承的特点

1、java只支持单继承,不支持多继承(即只能有一个父类)
2、Java支持多层继承

class A
class B extends A {}
class C extends B {}

3、子类和父类是一种相对的概念

抽象类

由来:父类中的方法,被它们的子类重写,子类各自实现的都不尽相同。父类的方法声明和方法主体,只有声明还有意义,而方法主体已经没有意义了。所以把没有方法主体的方法称为抽象方法,包含抽象方法的类为抽象类
抽象方法:使用abstract关键字修饰的方法。
抽象方法只包含一个方法名而没有方法体。
格式:

修饰符  abstract 返回值类型 方法名(参数)

如果一个类包含抽象方法,那么这个类就一定是抽象类

public abstract class man{
   public abstract int age(int a){

   }
}

抽象的使用
1、继承抽象类的子类必须重写父类中所有的抽象方法
2、必须由子类实现该父类的抽象方法
实例:

//父类
package moreclass;

public abstract class Father {      //抽象类

    public abstract void sex();      //抽象方法,无方法体
}


//子类
package moreclass;

public  class Son extends Father {

    public  void sex(){
        System.out.println("男");
    };
}


//子类方法调用并执行
package moreclass;

public class GetName {
    public static void main(String[] args) {
        Son s = new Son();
        s.sex();
    }
}

结果:
image.png
此时的方法重写,是子类对父类抽象方法的完成实现,我们将这种方法重写的操作,也叫做实现方法

抽象类的使用

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
    2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。
    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
    3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
    4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义 。

总结案例:群主发普通红包
群主发普通红包。某群有多名成员,群主给成员发普通红包。普通红包的规则:
1. 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取。
2. 成员领取红包后,保存到成员余额中。
请根据描述,完成案例中所有类的定义以及指定类之间的继承关系,并完成发红包的操作。

根据案例,理出逻辑关系
User类(父类):

package moreclass;

public class User {
    private  String name;
    private  double balance;
    public User(){

    }
    public User(String name,double balance){
        this.name=name;
        this.balance=balance;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public double getBalance() {
        return balance;
    }
    public void show() {
        System.out.println("用户名:"+ name +" , 余额为:" + balance + "元");
    }

}

群主类(子类):

package moreclass;

import java.util.ArrayList;

public class QunZhu extends User {
    public QunZhu(){

    }
    public QunZhu(String name,double balance){
        super(name,balance);
    }
    /*
群主发红包,就是把一个整数的金额,分层若干等份。
1.获取群主余额,是否够发红包.
不能则返回null,并提示.
能则继续.
2.修改群主余额.
3.拆分红包
*/
    public ArrayList<Double> send(int money,int account){
        double balance = getBalance();    //获取余额
        if(money>balance){
            return null;
        }
        setBalance(balance-money);       //修改余额
        ArrayList<Double> list = new ArrayList<>();   //ArrayList是集合,需要用引用数据类型,所以用但是Double,而不是double
        double m = money/account;
        for (int i = 0; i <account ; i++) {
            list.add(m);
        }
        return list;
    }
}

成员类(子类):

package moreclass;

import java.util.ArrayList;
import java.util.Random;


public class Member extends User {
    public Member(){

    }
    public Member(String name,double balance){
        super(name,balance);
    }
    public void kaihongbao(ArrayList<Double> list){

        Random r = new Random();    // 创建Random对象

        int index = r.nextInt(list.size());   // 随机生成一个角标

        Double money = list.remove(index);    // 移除一个金额

        setBalance(money);                   // 直接调用父类方法,设置到余额

    }
}

发红包:

package moreclass;

import java.util.ArrayList;
import java.util.Scanner;

public class FaHongBao {
    public static void main(String[] args) {
        QunZhu qz = new QunZhu("lang", 166);

        // 定义一个键盘输入
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入金额:");
        int money = sc.nextInt();
        System.out.println("请输入个数:");
        int count = sc.nextInt();
        // 发送红包

        ArrayList<Double> send = qz.send(money, count);


        if (send == null) {
            System.out.println(" 余额不足...");
            return;
        }
        // 创建三个成员
        Member m = new Member("lang1",0);
        Member m2 = new Member("lang2",0);
        Member m3 = new Member("lang3",0);
        // 打开红包
        m.kaihongbao(send);
        m2.kaihongbao(send);
        m3.kaihongbao(send);
        // 展示信息
        qz.show();
        m.show();
        m2.show();
        m3.show();
    }
}

运行结果:
image.png