面向对象包括三大特征:
-封装
-维承
-多态
封装的理解:封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问方法。
封装性包括:属性的封装,方法的封装,类的封装,组件的封装
当前主要讲解的是封装机制。为什么要封装?封装有什么好处/优点?
封装的优点:【提供简单的操作入口、独立体、重复使用、安全】
1、封装之后,对于那个事物来说,看不到这个事物比较复杂的那一面,只能看到该事物简单的那一面。
复杂性封装,对外提供简单的操作入口。
照相机就是一个很好的封装的案例,照相机的实现原理非常复杂,但是对于使用照相机的人来说,操作起来是非常方便的是非常便捷的。还有像电视机也是封装的,电视机内存实现非常复杂,但是对于使用者来说不需要关心内部的实现原理,只需要会操作遥控器就行。
2、封装之后才会形成真正的“对象”,真正的“独立体”
3、封装就意味着以后的程序可以重复使用,并且这个事物应该适应性比较强,在任何场合都可以使用。
4.封装之后,对于事物本身,提高了安全性。【安全级别高】
请看下面的例子
对于当前程序来说:
用户类(User)中的 “age” 属性在外部程序中可以随意访问,导致“age”属性的不安全。
一个用户对象(User)表示一个用户,用户的年龄不可能为负数,以下程序当中年龄值为负数,程序运行的时候并没有报错,这是当前程序存在的缺陷。
用户类(User.class)
public class User{
// 属性
int age;
}
用户测试类(UserTest.class)
public class UserTest{
public static void main(String[]args)
{
// 创建User对象
Useruser = new Userser();
// 读取年龄值【get】
System.out.println("该用户年龄:”+user.age);
// 修改年龄值【set】
user.age = 20;
// 读取年龄值【get】
System.out.println("该用户年龄:”+user.age);
// 修改年龄值
user.age = -100;
// 这里的age属性完全是暴露给外部程序的,对于程序员来说可以操作User对象当中的所有细节,导致User中部分数据不安全。
// 不建议这样,建议User类型进行封装,建议在外部程序中不能随意访问User对象当中的属性,这样可以保证属性的安全。
// 读取年龄值
System.out.println("该用户年龄:”+user.age);
如何进行封装?
封装的步骤:
1.所有属性私有化,使用private关键字进行修饰。private表示私有的。修饰的所有数据只能在本类中访问。
用户类(User.class)
public class User{
// 属性私有化
private int age;
}
用户测试类(UserTest.class)
public class UserTest{
public static void main(String[] args) {
// 创建User对象
User user = new User();
// 编译报错,age属性私有化,在外部程序中不能直接访问
// 从此之后age属性非常安全,但是有点太安全了。
// 对于目前的程序员来说,age熟悉彻底在外部访问不到了。
System.out.println("该用户年龄:”+user.age); // 访问不到age属性
}
}
2. 对外提供简单的操作入口,也就是说以后外部程序要访问age属性,必须通过这些入口进行访问。
- 对外提供两个公开的方法,分别是set方法和get方法
- 想修改age属性,调用set方法
- 想读取age属性,调用get方法
用户类(User.class)
public class User{
// 属性私有化
private int age;
// set方法没有返回值,因为set方法只负责修改数据
public void setAge(int a){
age = a;
}
// get方法
public int getAge(){
return age;
}
}
用户测试类(UserTest.class)
public class UserTest{
public static void main(String[] args) {
// 创建User对象
User user = new User();
// 编译报错,age属性私有化,在外部程序中不能直接访问
// 从此之后age属性非常安全,但是有点太安全了。
// 对于目前的程序员来说,age熟悉彻底在外部访问不到了。
// System.out.println("该用户年龄:”+user.age); // 访问不到age属性
// 使用set修改属性值
user.setAge(-100);
// 使用get读取属性值
System.iut.println(user.getAge());
}
}
这时你会想,这样也不安全啊,通过set方法还是能对数据进行随意修改。
不急,请看下面代码
用户类(User.class)
public class User{
// 属性私有化
private int age;
// set方法没有返回值,因为set方法只负责修改数据
public void setAge(int a){
//age = a;
// 编写业务逻辑代码,进行安全控制
if(a<0 || a>150 ){
System.out.println("对不起,您提供的年龄不合法!");
return;
}
// 程序可以执行到这来的话,说明a年龄是合法的,则进行赋值运算
age = a;
}
// get方法
public int getAge(){
return age;
}
}
3.set方法的命名规范:
// public void set+属性名首字母大写(形参){
// age = 修改的值;
// }
public void setAge(int a){
age = a;
}
4.get方法的命名规范:
// public int get+属性名首字母大写(){
// return 属性名;
// }
public int getAge(){
return age;
}
需要记住的点:
setter 和 getter 方法是没有 static 关键字修饰的。
有 static 关键字修饰的方法怎么调用: 类名.方法名(实参);
没有 static 关键字修饰的方法怎么调用:引用.方法名(实参);