Java基础之:OOP——封装

Java基础之:OOP——封装

面向对象编程OOP(Object Oriented Programming)的三大特征之一:封装

封装就是把类的一部分属性或方法等"隐藏"起来,若外部想要访问必须要通过封装类提供的方法才能对数据进行操作。通过封装我们可以将一些重要的数据放在内部保护起来。

封装的优点

  1. 隐藏方法实现的细节。

  2. 对数据进行验证,保证数据的安全合理。(例:Person类的age属性只能在1-120之间)

封装的实现

使用private访问修饰符 ,修饰属性或方法。对外界提供public修饰的方法对内部"隐藏"数据进行操作。

简单案例

Person类:


public class Person {
    public String name;
    private int age;
    private double salary;
    private String job;
​
    
    //构造器 + Set : 需要满足约束条件
    public Person(String name, int age, double salary, String job) {
        setName(name);
        setAge(age);
        setSalary(salary);
        setJob(job);
    }
    
    //重写toString方法  
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", salary=" + salary + ", job=" + job + "]";
    }
    
    public void setName(String name) {
        if (name.length() >= 2 && name.length() <= 6) {
            this.name = name;
        } else {
            System.out.println("姓名长度2-6,默认值小范");
            this.name = "小范";
        }
    }
​
    public void setAge(int age) {
        if (age >= 1 && age <= 120) {
            this.age = age;
        } else {
            System.out.println("年龄范围1-120,默认值18");
            this.age = age;
        }
    }
​
    public void setSalary(double salary) {
        if (salary <= 1000000 && salary >= 1) {
            this.salary = salary;
        }else {
            System.out.println("工资范围1-1000000,默认值10000");
            this.salary = 10000;
        }
    }
​
    public void setJob(String job) {
        this.job = job;
    }
​
    public double getSalary() {
        return salary;
    }
    
    public double getAge() {
        return age;
    }
    
    public String getJob() {
        return job;
    }
}

Test类:

 

public class Test {
​
    public static void main(String[] args) {
        //使用set get 方式
        Person person = new Person();
        person.setAge(120);
        person.setJob("teacher");
        person.setName("aaaaaaa");
        person.setSalary(12000);
        System.out.println("name: " + person.name);
        System.out.println("age:" + person.getAge());
        System.out.println("job:" + person.getJob());
        System.out.println("salary:" + person.getSalary());
        
        Person person = new Person("aaaaa", 8888,130000,"teacher");
        //重写了toString方法之后
        System.out.println(person.toString());
        
        //没有重写toString方法 则会返回  全类名 + 十六进制HashCode地址
        A a = new A();
        System.out.println(a);  //如果不写toString方法, 默认也是返回toString
        System.out.println(a.toString());   //返回十六进制
        System.out.println(a.hashCode());   //返回十进制
    }
    
}
​
class A{
    
}
​

说明:

  1. Person类:

    1. 使用private修饰符封装了 name,age,salary,job属性。

    2. 通过setXxx() 与 getXxx() 的方法实现给属性赋值以及访问属性值的功能。

    3. 这里注意不一定方法名一定是set和get,但一定都是使用public修饰的。

    4. 可以看到在setAge和setSalary时,都做了if判断。通过这种方面实现了外部输入数据的过滤,对内部的数据进行了保护。避免出现不符合语义的数据进入,例如Age = 2000,salary = -10000。

    5. 在Person类中我们还使用了有参构造器与set方法结合使用。这样既可以便捷的使用构造器给对象赋值,又可以使用set方法的数据保护机制。

    6. 重写了toString方法,"@Override"这个符号现在不用考虑,之后会讲到。具体同String方法说明在Test类中体现。

  2. Test类:

    1. 使用封装类的第一种方式,使用无参构造器,然后通过Person类提供的set方法为对象赋值。

    2. 数据输出时,也通过get方法去访问内部数据。可以看到这种方式实现时,代码量会比较大。

    3. 使用封装类的第二种方式,使用有参构造器,直接给对象赋值。

    4. 再使用toString方法输出对象的各属性信息。关于toString()方法的说明:

      1. 我们使用了一个测试类A来演示,在输出对象信息时会默认的调用toString方法。

      2. 若不对toString方法进行重写,输出的内容为:全类名 + 十六进制HashCode地址

      3. 由于我们在Person类中对toString方法进行了重写,所以会Person类的对象在输出时会按照我们定义的方式输出。

      4. 重写的概念会在之后的博客中给出。

案例总结

  1. 在对封装起来的属性写保护机制的时候,尽量在输入数据出错时附带一个默认值,这样可以保证整个程序不会出现"0"或"null"等无意义数据存在。

  2. 对象赋值可以灵活的选择set方法和有参构造器两种方式。

  3. 输出对象信息时,尽量使用toString方法,可以使用 "System.out.println(对象名);"的方式,简洁明了。这里实际上是 "System.out.println(对象名.toString());" 只不过toString方法默认隐藏。

 

接下来我们看两个对于封装类的实际应用,为了代码方便阅读这里将各个类写在了一起,但在实际开发中应该保证一个类一个文件,所有类在同一个包下。

应用案例1

定义一个Person类 {name, age, job}, 初始化Person 对象数组,有3个person对象, 并按照 age 从 大到小进行排序,提示,使用冒泡排序.

public class Test {
    public static void main(String[] args) {
        Person[] person = new Person[3];
        // 初始化对象数组
        person[0] = new Person("小范", 20, "老师");
        person[1] = new Person("小黄", 18, "店长");
        person[2] = new Person("小雨", 19, "舞蹈老师");
​
        // 遍历显示Person数组
        for (int i = 0; i < person.length; i++) {
            System.out.println(person[i]); // 默认就带有toString方法
        }
​
        sort(person); // 排序
        System.out.println("===========排序后=============");
​
        for (int i = 0; i < person.length; i++) {
            System.out.println(person[i].toString());
        }
    }
​
    // 冒泡排序
    private static void sort(Person[] person) {
        // 临时对象
        // Person temp = new Person(); 自己的思路
​
        // 冒泡排序 自己的思路
//      for (int i = 0; i < person.length - 1; i++) {
//          for (int j = 0; j < person.length - 1 - i; j++) {
//              if (person[j].getAge() > person[j + 1].getAge()) {
//                  // 使用 temp 对象 ,临时保存 , 将堆中的内容进行改变
//                  temp.setName(person[j].getName());
//                  temp.setJob(person[j].getJob());
//                  temp.setAge(person[j].getAge());
//                  
//                  person[j].setName(person[j + 1].getName());
//                  person[j].setJob(person[j + 1].getJob());
//                  person[j].setAge(person[j + 1].getAge());
//
//                  person[j + 1].setName(temp.getName());
//                  person[j + 1].setJob(temp.getJob());
//                  person[j + 1].setAge(temp.getAge());
//              }
//          }
//      }
​
        // 冒泡 韩老师的思路
        Person temp = null;
​
        // 冒泡排序 韩老师的思路
        for (int i = 0; i < person.length - 1; i++) {
            for (int j = 0; j < person.length - 1 - i; j++) {
                if (person[j].getAge() > person[j + 1].getAge()) {
                    // 使用 temp 对象 ,临时保存 ,使用引用地址来进行交换
                    temp = person[j];
                    person[j] = person[j + 1];
                    person[j + 1] = temp;
                }
            }
        }
    }
​
}
​
class Person {
    private String name;
    private int age;
    private String job;
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public String getJob() {
        return job;
    }
​
    public void setJob(String job) {
    this.job = job;
    }
​
// 有参构造器
   public Person(String name, int age, String job) {
    this.name = name;
    this.age = age;
    this.job = job;
    }
​
// 无参构造器
  public Person() {
    }
​
// 输出打印Person信息
   public String toString() {
    return "Person [name=" + name + ", age=" + age + ", job=" + job + "]";
    }
​
}

 

应用案例2

计算圆的面积,圆柱的体积。

public class Test {
    public static void main(String[] args) {
        Circle circle = new Circle();
        Cylinder cylinder = new Cylinder();
        
        circle.setRadius(2.5);
        System.out.printf("圆半径:%.2f  圆面积:%.2f
",circle.getRadius(),circle.findArea());
        
        cylinder.setLength(3.1);
        System.out.printf("圆柱高:%.2f  圆柱体积:%.2f
",cylinder.getLength(),cylinder.findVolume(circle));
    }
}
​
/*
 *  class Circle(圆)
 *  -radius :double 
    Circle(): 构造方法,将radius 私有属性初始化为1
    +setRadius(double radius) : void
    +getRadius(): double
    +findArea():double  计算圆的面积
​
 */
class Circle{
    private double radius;
​
    public Circle() {       //构造器
        this.radius = 1;
    }
​
​
    public double getRadius() {
        return radius;
    }
​
    public void setRadius(double radius) {
        this.radius = radius;
    }
    
    public double findArea() {
        return radius * radius * Math.PI; //Math.PI 返回 3.14.....
    }
}
​
/*
 *   class Cylinder(圆柱)
 *   -length:double //高度
 *  Cylinder():  构造方法,将length属性初始化为1
    +setLength(double length):void
    +getLength():double
    +findVolume() :double   计算圆柱体积
 *   
*/
class Cylinder{
    private double length;
    
    public Cylinder(double length) {
        this.length = length;
    }
​
    
    public Cylinder() {
        this(1);    //调用上面的有参构造,将length初始化为1
    }
​
​
    public double getLength() {
        return length;
    }
​
    public void setLength(double length) {
        this.length = length;
    }
    
    public double findVolume(Circle circle) {   //使用Circle对象作为参数传递
        return circle.findArea() * length;  //直接使用findArea()方法
    }
}

 

 

原文地址:https://www.cnblogs.com/SongHai/p/14074357.html