面向对象(JAVA)三大特性之------封装

一:封装的定义概念及优点。
封装的官方定义是:封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。简单来说,封装就是把数据和对这些数据的操作放在一起,同时,更深入的讲就是用这些操作将这些数据隐藏起来,外界只能看见操作,却看不见数据。必须要注意的是,封装不是简单地将东西放在一起,必须要进行相应的操作,防止内部的数据公开的被外界访问。
封装的基本原则是将对象的内部和界面分隔开来,对象内部的数据和内部的操作被隐藏起来,公开的只是可以对外的操作,这些公开的部分就称之为对象的界面,所以,外界只能通过发消息给界面,通过界面来操纵数据,而不能直接操纵数据。
封装的优点是:
1:封装的主要功能在于我们能修改自己的代码,而不用修改那些调用我们代码的程序,这极大地减小了耦合。
2:同时封装也可以让程序更容易维护和理解,也极大地增强了程序的安全性。

二:实际操作和理解。
上边我们了解了封装的概念原则,和他的优点,下边我们同过实际的代码来进一步理解。

//实体类Person
public class Person {
    public String name;
    public int age;
    public void showInfo(){
        System.out.println("我叫"+name+", 我今年"+age+"岁了");
    }
}

//测试类TestPerson
public class TestPerson {
    public static void main(String[] args){
        Person p = new Person();
        p.age=33;
        p.name("张三");
        p.showInfo();
    }
}

在上面的代码块中对于属性age和name我们都可以通过对象名点属性的方法进行赋值:p.age=*; 哎,此时你如果觉得对象名点属性很是麻烦,可以添加构造方法,进行便捷的属性复制。代码块如下:

//实体类Person
public class Person {
    public String name;
    public int age;

    public Person(String name,int age){
        this.name=name;
        this.age=age;
    }
    public void showInfo(){
        System.out.println("我叫"+name+", 我今年"+age+"岁了");
    }
}

//测试类TestPerson
public class TestPerson {
    public static void main(String[] args){
        Person p = new Person("张三",33);
        p.showInfo();
    }
}

通过构造函数的方法进行赋值更加快捷一点。尤其是在实例化了多个对象的时候,使用对象点属性进行赋值更加繁琐。但是有了构造函数还能用对象名点属性的方式进行对象属性的赋值么?请看下方代码:

//实体类Person
public class Person {
    public String name;
    public int age;

    public Person(String name,int age){
        this.name=name;
        this.age=age;//输入赋值入口
    }
    public void showInfo(){//输出结果出口
        System.out.println("我叫"+name+", 我今年"+age+"岁了");
    }
}

//测试类TestPerson
public class TestPerson {
    public static void main(String[] args){
        Person p = new Person("张三",33);
        p.age=22;
        p.showInfo();
    }
}

上述代码使用了构造函数进行初始化赋值了,但是又使用了 p.age=22;即对象名点属性的方式进行赋值操作,那有没有用呢?再调用showInfo方法的时候,显示age为22,也就是说将上面的构造方法的赋值操作给覆盖了。
卧槽!!那问题来了,如果我给age赋一个负数的值呢。如: p.age=-22;答案仍然是显示负的22,这不符合逻辑啊,我们应该在程序中添加一个代码块进行判断啊,那这个代码块应该添加在哪啊是在输入赋值入口(代码中有标记)进行判断呢,还是在输出结果出口(代码中有标记)进行判断呢?=====答案当然是在输入赋值入口进行判断了!!!上代码块:

//实体类Person
public class Person {
    public String name;
    public int age;

    public Person(String name,int age){
        this.name=name;
        if(age<=0){
            age=1;
        }else{
            this.age=age;
        }
    }
    public void showInfo(){
        System.out.println("我叫"+name+", 我今年"+age+"岁了");
    }
}

//测试类TestPerson
public class TestPerson {
    public static void main(String[] args){
        Person p = new Person("张三",33);
        //p.age=-22;//此赋值方式仍然成立
        p.showInfo();
    }
}

此时当你再进行实例化对象,并且通过构造函数进行赋值的时候他就会自动判断你的age属性值是否是符合规范的,并进行相应的操作。但是!!!!,经过上一个代码块的操作可以得到,直接使用对象名点属性的操作仍然可以进行赋值操作!!!那我赋值负数岂不是也可以覆盖构造函数的初始化的值??!!!!,答案是肯定的,这个时候,我们就需要引进一个重要的概念——修饰符!!!
修饰符public表示任何类的任何方法都可以进行访问。修饰符private表示只有成员所在的类中的方法里可以访问。
所以可以通过设置成员变量的访问修饰符为private控制他只能被自己的类的成员方法访问。上代码:

//实体类Person
public class Person {
    private String name;
    private int age;

    public Person(String name,int age){
        this.name=name;
        if(age<=0){
            age=1;
        }else{
            this.age=age;
        }
    }
    public void showInfo(){
        System.out.println("我叫"+name+", 我今年"+age+"岁了");
    }
}

//测试类TestPerson
public class TestPerson {
    public static void main(String[] args){
        Person p = new Person("张三",33);
        //p.age=-22;//无法进行赋值了。
        p.showInfo();
    }
}

把这个person类中的属性都设置成私有的了,不允许外界看到,并且操作我这个属性只能通过一些公开的界面进行操控!!!,而通过构造函数这个界面进行赋值操作,必然要进行age的合法性判断,所以,安全性得到了一定的保障。
用比较正式的话讲就是,在实体类中属性被private修饰符修饰,在测试类中就不能直接对这个属性进行访问了,必须要通过实体类中的public方法进行访问(这个public方法,必须是和要使用的属性有联系的)。
但是你只是想对某一个属性进行赋值或者某个属性的属性值提取使用呢?
在这里就需要对每一个私有属性设置一对公有的set、get方法,这样外界就可以通过公有的set、get方法对这些私有的属性进行操作了。上代码:

//实体类Person
public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        if (age<=1) {
            age=1;
        }
        this.age = age;
    }

    public Person(String name,int age){
        this.name=name;
        if(age<=0){
            age=1;
        }else{
            this.age=age;
        }
    }
    public void showInfo(){
        System.out.println("我叫"+name+", 我今年"+age+"岁了");
    }
}

//测试类TestPerson
public class TestPerson {
    public static void main(String[] args){
        Person p = new Person("张三",33);
        //p.age=-22;//无法进行操作了。
        p.showInfo();
        //p.age=22;//无法进行操作
        //p.setAge(-33);//可以进行操作,但是输入结果受到判断并且执行相应操作
        //int age1= p.getAge();//取到age=1,赋给变量age
        //p.setName("张三2");//可以进行赋值,构造函数赋值被覆盖。
        //String name1=p.getName();//取到name,赋给变量name1
        //System.out.println("我叫"+name1+", 我今年"+age1+"岁了");
    }
}

上述代码块中对实体类中的属性都进行了私有化处理(private),测试类中只能通过访问调用实体类中相对应的public方法 ,才能对相对应的属性进行操作。
这就是封装。
三:总结。
1:将实体类中的变量设置为private,使得只有内部的方法可以访问。
2:在测试类中调用实体类中的公有的方法对属性进行操作。
3:不止set,get方法,构造方法也是属于外界可以使用的公有方法,在初始化对象的时候,可以直接访问并操作属性,所以涉及到安全性验证的时候必须要加上判断条件。
4:封装的优点有很多,其中涉及到再开发的是,只要保持程序与外界的接口不变,那么外界使用者就不用改变自己的代码,而程序内部可以进行改动,而这些改动对于外界是绝对不可见的。这种对于创建者有着进一步发展和创造空间同时又不影响使用者的利益,才是封装的意义所在。

猜你喜欢

转载自blog.csdn.net/sun_dongliang/article/details/80554830