Java面向对象特征1之封装与隐藏
1 - 为什么需要封装、封装的作用和含义?
/*
我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部结构吗?有必要碰电动机吗?
我们程序设计追求“高内聚,低耦合”。
高内聚:类的内部数据操作细节自己完成,不允许外部干涉
低耦合:仅对外暴露少量的方法用于使用
隐藏对象内部的复杂性,只对外公开简单的接口。便于外界调用,从而提高系统的可扩展性、可维护性。通俗的说,把该隐藏的隐藏起来,该暴露的暴露出来。这就是封装性的设计思想。
*/
1-面向对象的特征1:封装与隐藏
/*面向对象的特征1:封装与隐藏 * * 1-问题的引入: * 当我们创建一个类的对象以后,我们可以通过"对象.属性"的方式,对对象的属性进行赋值,这里赋值操作要受到属性数据类型和存储 * 范围的制约,除此之外,没有其他制约条件。但是,在实际问题中,我们往往需要给属性赋值,介入额外的限制条件,这个条件就不 * 能在属性声明时体现。 * 同时,我们需要避免用户再使用"对象.属性"的方式对属性进行赋值,则需要将属性声明为私有的(private) * -->此时,针对属性就体现了封装性。 * 2-封装性的体现 * 类的属性abc私有化(private),同时,提供公共的(public)方法来获取(getAbc)和设置(setAbc)此属性的值 * * 3-扩展:①如上 ② 不对外暴露私有的方法 ③ 单例模式 * */ public class EncapsulationTest { public static void main(String[] args) { // 实例化 Animal animal = new Animal(); animal.name = "大黄"; // animal.age = 1; 不能再访问 // animal.legs = 4; animal.setLegs(4); animal.show(); // animal.legs = -4; animal.setLegs(-2); // 0 animal.show(); // 访问私有属性 int legNumber = animal.getLegs(); System.out.println(legNumber); } } class Animal{ String name; // int age; private int age; // int legs; 腿的个数 private int legs; // 设置私有的权限修饰符,这样除自身作用域外,不能访问到此属性 public void eat() { System.out.println("动物进食"); } public void show() { System.out.println("name:"+name+"\nage:"+age+"\nlegs:"+legs); } public void setLegs(int i) { if(i > 0 && i % 2 == 0) { legs = i; }else { legs = 0; // 也可以抛出异常(后面介绍) } } // 对象属性获取 public int getLegs() { return legs; } // 提供关于age属性get和set方法,外部才能访问到此属性 public int getAge() { return age; } public void setAge(int i) { if(i > 0) { age = i; }else { // 抛出异常 age = 18; } } }
2-封装性的体现:需要权限修饰符的来配合。
①Java规定的4种权限(从小到大排列):private,缺省(什么都不写),protected,public
②4种权限可以用来修饰类及类的内部结构:属性、方法、构造器、内部类
③具体的,4中权限都可以用来修饰类的内部结构:属性、方法、构造器、内部类。修饰类的话只能使用:缺省、public
2 - 四种访问权限修饰符
3 - 总结封装性
Java提供4种权限修饰符来修饰类及类的内部结构,体现类及类的内部结构在被调用时的可见性的大小。
封装性的4个体现:
体现1:将类的属性私有化(private),提供公共的方法(public)来获取(get)和设置(set)此属性的值
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
体现2:不对外暴露的私有方法
体现3:单例模式(将构造器私有化 )
体现4:如果不希望类在包外被调用,可以将类设置为缺省的
4 - 封装与隐藏练习
/*
创建程序,在其中定义两个类:Person和PersonTest类。定义如下:
用setAge()设置人的合法年龄(0~130),用getAge()返回人的年龄。
在PersonTest类中示例华Person类的对象b,调用setAge()和getAge()方法,体会Java的封装性。
*/
package com.Encapsulation.test; /* * 创建程序,在其中定义两个类:Person和PersonTest类。定义如下: * 用setAge()设置人的合法年龄(0~130),用getAge()返回人的年龄。 * */ public class Person { private int age; public int getAge() { return age; } public void setAge(int i) { if(i > 0 && i < 130) { age = i; }else { // 抛出异常,这里设置成-1,表示不合法 // age = -1; throw new RuntimeException("传入的数据不合法!"); } } }
package com.Encapsulation.test; /* * 在PersonTest类中示例华Person类的对象b,调用setAge()和getAge()方法,体会Java的封装性。 */ public class PersonTest { public static void main(String[] args) { // TODO Auto-generated method stub Person person = new Person(); person.setAge(22); // 设置年龄 int personAge = person.getAge(); // 获取年龄 System.out.println(personAge); // person.age = 22; 编译不通过 } }
5 - 类的成员之构造器
/*
类的结构之一:属性
类的结构之二:方法
类的结构之三:构造器(或构造方法、constructor)的使用
1-构造器的作用:
①创建对象
②给对象进行初始化
2-说明
①如果没有显示的定义类的构造器的话,则系统默认提供一个空参的构造器
②定义构造器的格式:权限修饰符 类名(形参列表){}
③一个类中定义的多个构造器,彼此构成重载
④一旦我们显示的定义了类的构造器之后,系统就不在提供默认的空参构造器
⑤一个类中至少有一个构造器
*/
3-代码示例
public class PersonTest{ public static void main(String[] args) { // 创建类的对象:new + 构造器 Person p = new Person(); p.eat(); Person p1 = new Person("howie",22); // 使用构造器 p1.study(); } } class Person { // 属性 String name; int age; // 构造器 public Person(){ // 构造器1 System.out.println("执行构造器呀。"); } public Person(String s) { // 构造器2 name = s; } public Person(String s,int i) { // 构造器3 name = s; age = i; } // 方法 public void eat() { System.out.println("人吃放!"); } public void study() { System.out.println("人要学习!"); } }
6 - 构造器+封装+隐藏的练习
/*
编写两个类,TriAngle和TriAngleTest,其中TriAngle类中声明私有的底边长base和高height,同时声明公共方法访问私有变量。此外,提供类必要的构造器。另一个类中使用这些公共方法,计算三角形的面积。
*/
package com.company; /* * 编写两个类,TriAngle和TriAngleTest,其中TriAngle类中声明私有的底边长base和高height,同时声明公共方法访问私有变量。 * 此外,提供类必要的构造器。另一个类中使用这些公共方法,计算三角形的面积。 */ public class TriAngle { private double base; // 底边长 private double height; // 高 public TriAngle(){ } public TriAngle(double i,double h){ base = i; height = h; } public double getBase(){ return base; } public void setBase(double i){ base = i; } public void setHeight(double h){ height = h; } public double getHeight(){ return height; } }
package com.company; public class TriAngleTest { public static void main(String[] args) { // 方法1 TriAngle t1 = new TriAngle(); System.out.println("base="+t1.getBase()+"\theight="+t1.getHeight()); t1.setBase(4); t1.setHeight(3); double s1 = (t1.getBase() * t1.getHeight()) / 2; System.out.println("方法1\t三角形的面积="+s1); // 方法2 TriAngle t2 = new TriAngle(4,3); System.out.println("base="+t2.getBase()+"\theight="+t2.getHeight()); double s2 = (t1.getBase() * t1.getHeight()) / 2; System.out.println("方法2\t三角形的面积="+s2); } }
7 - 属性赋值的过程
/*
截止到目前,我们已经血量很多位置可以对类的属性赋值。现总结这几位位置,并指明赋值的先后顺序。
赋值的位置
①默认初始化
①显示初始化
③构造器中初始化
④通过"对象.属性"或"对象.方法"的方式赋值
赋值的先后顺序:
① - ② - ③ - ④
*/
/* * 总结属性赋值的先后顺序 * * 结论:1 - 2 - 3 - 4 */ public class UserTest { public static void main(String[] args) { // 验证1 默认初始化为0 // 验证2 显示赋值 User u1 = new User(); System.out.println(u1.age); // 1 // 验证3 构造器中赋值 User u2 = new User(2); System.out.println(u2.age); // 2 // 验证4 通过"对象.属性"或"对象.方法"的方式赋值 User u3 = new User(); u3.setAge(22); System.out.println(u3.getAge()); } } class User{ String name; int age = 1; // 设置构造器 public User(){ } public User(int i){ age = 2; } // 设置方法 public void setAge(int i){ age = i; } public int getAge(){ return age; } }
8 - 知识扩展
JavaBean
1 JavaBean是一种Java语言写成的可重用组件。
2 所谓javaBean,是指符合如下标准的Java类:
✔ 类是公共的
✔ 有一个无参的公共的构造器
✔ 有属性,且有对应的get、set方法
3 用户可以使用JavaBean将功能、处理、值、数据库访问和其他任何可以 用Java代码创造的对象进行打包,并且其他的开发者可以通过内部的JSP 页面、Servlet、其他JavaBean、applet程序或者应用来使用这些对象。用 户可以认为JavaBean提供了一种随时随地的复制和粘贴的功能,而不用关 心任何改变。
/* * JavaBean是一种Java语言写成的可重用组件,所谓JavaBean,是指符合以下标准的Java类: * ①类是共共的 * ②有一个无参的公共的构造器 * ③有属性,且有对应的get、set方法 */ public class Customer { private int ID; private String name; public Customer(){ } public void setID(int ID){ this.ID = ID; } public int getID(){ return ID; } public void setName(String s){ this.name = s; } public String getName(){ return name; } }
9 - this关键字
1-什么是this?
1 在Java中,this关键字比较难理解,它的作用和其词义很接近。
✔ 它在方法内部使用,即这个方法所属对象的引用;
✔ 它在构造器内部使用,表示该构造器正在初始化的对象。
2 this 可以调用类的属性、方法和构造器
3 什么时候使用this关键字呢?
✔ 当在方法内需要用到调用该方法的对象时,就用this。 具体的:我们可以用this来区分属性和局部变量。 比如:this.name = name;
2-this(当前对象)关键字的使用
1-this可以用来修饰:属性、方法、构造器
2-this修饰属性和方法:首先this理解为 当前对象 或 当前正在创建的对象
①在类的方法中,我们可以使用"this.属性"或"this.方法"的方式,调用当前对象属性或方法,但是我们 通常省略 this。特殊的如果方法的形参和类的属性同名时,则不能省略必须使用"this.属性"表明此变量是属性,而非形参。
②在类构造器中,我们可以使用"this.属性"或"this.方法"的方式,调用当前正在创建的对象属性或方法,但是我们 通常省略 this。特殊的如果构造器的形参和类的属性同名时,则不能省略,必需使用 "this.属性" 表明此变量是属性,而非形参。
3-this调用构造器
① 我们在类的构造器中,可以显示的使用"this(形参列表)"方式,调用本类中指定的其他构造器
② 构造器中不能通过"this(形参列表)"方式调用自己
③如果一个类中有n个构造器,则最多有n - 1构造器中使用了"this(形参列表)"
④规定:"this(形参列表)"必须声明在当前构造器的首行
⑤构造器内部,最多只能声明一个"this(形参列表)",用来调用其他的构造器
public class PersonTest { public static void main(String[] args) { // TODO Auto-generated method stub Person p1 = new Person("howie"); p1.setAge(22); System.out.println(p1.getAge()); // p1.eat(); Person p2 = new Person("alex",18); int res = p2.getAge(); System.out.println(res); } } class Person{ private String name; private int age; // 构造器 public Person() { System.out.println("111111111111111111111111111111"); } public Person(String name) { this(); this.name = name; } public Person(int age) { this(); this.age = age; } public Person(String name,int age) { this(age); this.name = name; // this.age = age; } // 方法 public void setName(String name) { this.name = name; // this修饰属性 } public String getName() { return name; } public void setAge(int age) { this.age = age; // this修饰属性 } public int getAge() { return age; } public void eat() { System.out.println("人吃饭"); this.sleep(); // this修饰方法 } public void sleep() { System.out.println("人睡觉"); } }
10 - package 和 imort 关键字的使用
// package com.company; /* * 1-package关键字的使用 * ①为了更好的实现项目中类的管理,提供包的概念 * ②使用package声明类或接口所属的包,声明在源文件的首行 * ③包,属于标识符,遵循标识符的命名规则,规范(小写),见名知意 * ④每"."一次,就代表一层文件目录 * 注意:同一个包下,不能命名同名的接口、类,不同包下,可以命名同名的接口、类 * * 2-import(导入) 关键字的使用 * ①在源文件中显示的使用import结构导入指定包下的类、接口 * ②声明在包的声明和类的声明之间 * ③如果需要导入多个结构,则并列写出即可 * ④可以使用"xxx.*"的方式,表示可以导入xxx包下的所有结构 * ⑤如果使用的类或接口是java.lang包下定义的,则可以省略import结构 * ⑥如果使用的类或接口是本包下定义的,则可以省略import结构 * ⑦如果在源文件中,使用了不同包下同名的类,则必须至少有一个类需要以全类名的方式显示(import com.company.类名;) * ⑧使用"xxx.*"的方式表示可以调用xxx包下的所有结构,但是如果使用的是xxx子包下的结构,则仍需要显示全类名 * ⑨import static 导入指定类或接口中的静态结构 */ import java.util.Arrays; // import 的使用 public class PackageImportTest { public static void main(String[] args) { // TODO Auto-generated method stub String info = Arrays.toString(new int[] {1,2,3}); System.out.println(info); // [1, 2, 3] PersonTest personTest = new PersonTest(); } }
11 - MVC设计模式
流程解析