什么是封装
所谓的封装就是把数据项和方法作为一个独立的整体隐藏在对象的内部,具体的实施细节不对外提现,仅仅保留有限的外部接口,封装外的用户只能通过接口来进行操作。就好比开启一台电脑需要进行很多个步骤,电源供电、BIOS自检、查找硬件等等一系列动作,而我们只需要按下开机按钮,其余的动作都是电脑内部完成的,这里就可以看作是电脑对启动的一系列动作进行了封装,给提供了开机按钮供我们调用。
为何需要封装
首先,从程序安全性上来说,暴露在外面的细节被隔离掉,要想修改内部的数据,必须使用提供的特定方法,而这些方法中又做了限制,可以确保值设置合法的值。
其次,封装后的程序只对外提供特定的接口以供调用,而其内部如何实现与外界无关,所以当修改程序的时候,只要保证接口正确,其内部如何实现可以自己随意去修改,而不用担心会受到外界值的影响。
JAVA中的权限控制符
private:只能自己访问使用
public:允许所有外部类访问使用
protected:允许子类和同包类访问使用
default:只允许同类或同包使用
JAVA中的包
JAVA中为了解决类的命名问题,实现类文件的管理引入的包机制。通常我们将一组功能相同的类放在同一个包下,从而形成逻辑上的类的集合。
程序的第一行使用
package 包名
来表示该类位于某个包中。一旦类中使用的package语句,就意味着该源文件里面定义的所有类都属于这个包。
如果要使用其他包中的类,则需要是用import关键字来导入指定包下的某个类。
java中的常用包:
java.lang:该包包含了JAVA语言的核心类,如String、Math、System和Thread等,使用这个包下的类无须使用import语句导入,系统会自动导入该包下的所有类
java.util:这个包包含了JAVA的大量工具类、接口和集合框架类、接口,例如Arrays和List、Set等
java.net:这个包下包含了一些JAVA网络编程相关的类和接口
java.io:这个包包含了一些JAVA输入输出的相关类和接口
java.sql:这个包包含了JAVA进行JDBC数据库变成的相关类和接口
如何封装
1、把所有的属性藏起来。
2、把尽可能多的东西藏起来.对外提供简捷的接口。
3、对操作接口进行合法性验证
class Animal { // 定义private权限的name和age属性 private String name; private int age; // 提供对外使用的getName、setName、getAge和setAge方法 // 在方法内部进行合法性验证 public String getName() { return name; } public void setName(String name) { if (name.length() <= 0) { System.out.println("名字太短啦"); } else { this.name = name; } } public int getAge() { return age; } public void setAge(int age) { if (age <= 0) { System.out.println("年龄太小啦"); } else { this.age = age; } } } public class Test { public static void main(String[] args) { Animal animal = new Animal(); // 执行时候,如果直接使用animal.name,系统会抛出异常 // Exception in thread "main" java.lang.Error: Unresolved compilation problem: // The field Animal.name is not visible // animal.name = "dog"; //必须使用animal.setName()来设置其name属性 //animal.setName("");//直接传入空字符串,又会提示“名字太短啦” animal.setName("dog"); } }
JAVA中的this
this关键字总是指向调用该方法的对象。根据this出现位置的不同,this作为对象的默认引用有两种情形:
1.构造器中引用该构造器正在初始化的对象
public class ThisDemo { // 定义一个名为num的成员变量 public int num; public ThisDemo () { // 使用this代表该构造器正在初始化的对象 // 下面的代码将会把该构造器正在初始化的对象的foo成员变量设为6 this.num= 6; } public static void main(String[] args) { // 所有使用ThisDemo 创建的对象的num成员变量均为6 System.out.println(new ThisInConstructor().num); } }
2.在方法中引用调用该方法的对象
public class Dog { // 定义一个jump()方法 public void jump() { System.out.println("正在执行jump方法"); } // 定义一个run()方法,run()方法需要借助jump()方法 public void run() { this.jump(); System.out.println("正在执行run方法"); } }
如果方法里有个局部变量和成员变量同名,但程序又需要在该方法里访问这个被覆盖的成员变量,则必须使用this前缀。
public class Test { private int num = 13; public void setNum(int num) { this.num = num; } public int getNum() { return num; } public static void main(String[] args) { Test t = new Test(); t.setNum(15); System.out.println(t.getNum()); } }
this引用也可以用于构造器中作为默认引用,由于构造器是直接使用new关键字来调用,而不是使用对象来调用,所以this在构造器中代表该构造器正在初始化的对象
public class ReturnThis { public int age; public ReturnThis grow() { age++; // renturn this返回调用该方法的对象 return this; } public static void main(String[] args) { ReturnThis rt = new ReturnThis(); // 可以连续调用同一个方法 rt.grow().grow().grow(); System.out.println("re的age成员变量值是:" + rt.age); //re的age成员变量值是:3 } }
this()表示调用构造方法(需注意:构造函数调用必须在构造函数中的第一条语句)
public class Test { public Test() { System.out.println("无参构造函数"); } public Test(int num) { this(); System.out.println("一个参数的构造函数"); } public static void main(String[] args) { Test t = new Test(2); } } //输出结果为:无参构造函数 一个参数的构造函数