目录
课前先导
一、private权限修饰符
二、get()/set()方法【getXxx()和setXxx()]
三、this关键字的使用
四、封装
课前先导
前面我们学习了怎么通过创建对象给对象的属性赋值;但是通过对象直接给属性赋值,只要数据类型正确,可以给属性赋任何值,这种赋值方法是不严谨的,比如给年龄个负数:
创建一个类;定义姓名和年龄属性以及show()方法:
public class Draft {
String name;
int age;
public void show(){
System.out.println("姓名是:"+name+",年龄:"+age);
}
}
创建测试类:
public class DraftTest {
public static void main(String[] args){
Draft zs = new Draft(); //创建第一个对象
zs.name = "张三";
zs.age = 20;
zs.show();
Draft ls = new Draft(); //创建第二个对象
ls.name = "李四";
ls.age = -30;
ls.show();
}
}
控制台输出:
姓名是:张三,年龄:20
姓名是:李四,年龄:-30
通过上面的代码我们可以看到,普通的通过对象给属性赋值,不太严谨,只要数据类型正确,就能随意给属性赋值;可年龄怎么能给负数呢!难道现在都能借贷生命了吗?所以我们要给数据的输入定个规范。
一、private权限修饰符
Java中的权限修饰符一共有四个;分别是:
public 、protected 、默认 、private;
这里我们看一下private权限修饰符:
英文单词 private:私有的,自用的。
private权限修饰符是Java权限修饰符中权限最小的修饰符,可以修饰成员变量和成员方法,使用 private 修饰的 成员 只能在 当前类的内部 被访问(只要成员变量或成员方法被private修饰了,那么就只能在这一个类中使用)。
作用:
保护成员不被别的类使用,被private修饰的成员只在本类中才能访问。
public class Draft {
private String name;
private int age;
public void show(){
System.out.println("姓名是:"+name+",年龄:"+age);
}
}
public class DraftTest {
public static void main(String[] args){
Draft zs = new Draft(); //创建第一个对象
zs.name = "张三";
zs.age = 20;
zs.show();
Draft ls = new Draft(); //创建第二个对象
ls.name = "李四";
ls.age = -30;
ls.show();
}
}
这里我们在把属性用private修饰后;再来看一下运行结果(这里用的开发工具是myeclipse):
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The field Draft.name is not visible
The field Draft.age is not visible
The field Draft.name is not visible
The field Draft.age is not visible
at com.lj.java01.DraftTest.main(DraftTest.java:7)
运行结果是我们的程序报错了。上面测试类中我们通过对象给属性赋了四次值,运行结果就给了我们四个"The field Draft.age is not visible";这句英文的意思大概是:这个Draft.age不能访问。不能访问就不能随意修改属性的值,这样一来我们的代码安全性就大大提高了,只要提升了代码的安全性,就算提升了我们代码的档次,月薪上万指日可待。
不过;不能访问就不能给属性赋予我们想要的值,那不嗝屁了吗!这代码不就成了“死”代码,没什么用了吗?别急,请看下文。
二、get()/set()方法【getXxx()和setXxx()]
上文讲到只要成员方法和成员变量被private修饰,那么就不能被其他的类访问,在提升代码安全性的同时,也让我们的代码成了“死”代码,什么都做不了,对我们来说就没什么用了。下面我们让他“活”起来:
英文单词 get:获得 set:设置
针对private修饰的成员变量,如果需要被其他类使用,提供相应的操作
提供“get变量名()”方法,用于获取成员变量的值,方法用public修饰
提供“set变量名(参数)”方法,用于设置成员变量的值,方法用public修饰
public class Draft {
private String name;
private int age;
public String getName() { //获取name的值 name的数据类型是String
return name;
}
public void setName(String n) { //设置name的值
name = n;
}
public int getAge() { //获取age的值 age的数据类型是int
return age;
}
public void setAge(int m) { //设置age的值
age = m;
}
public void show(){
System.out.println("姓名是:"+name+",年龄:"+age);
}
}
public class DraftTest {
public static void main(String[] args){
Draft zs = new Draft(); //创建第一个对象
zs. setName("张三"); //使用set方法设置成员变量name的值
zs.setAge(20); //使用set方法设置成员变量age的值
zs.show();
Draft ls = new Draft(); //创建第二个对象
ls.setName("李四"); //使用set方法设置成员变量name的值
ls.setAge(-30); //使用set方法设置成员变量name的值
ls.show();
}
}
姓名是:张三,年龄:20
姓名是:李四,年龄:-30
也可以不调用show()方法来输出,通过使用get()方法来获取成员变量的值。
public class DraftTest {
public static void main(String[] args){
Draft zs = new Draft(); //创建第一个对象
zs. setName("张三"); //使用set方法设置成员变量name的值
zs.setAge(20); //使用set方法设置成员变量age的值
System.out.println("我叫"+zs.getName()+",今年"+zs.getAge()+"岁。");
Draft ls = new Draft(); //创建第二个对象
ls.setName("李四"); //使用set方法设置成员变量name的值
ls.setAge(-30); //使用set方法设置成员变量name的值
System.out.println("我叫"+ls.getName()+",今年"+ls.getAge()+"岁。");
}
}
我叫张三,今年20岁。
我叫李四,今年-30岁。
这里我们看到,最后一个我们依旧给它一个负值,依然贷命在人间生活;好像用不用private都没什么区别,那么,这时候就应该体现get()/set()方法的价值了,在set()方法中可以对参数进行判断
public class Draft {
private String name;
private int age;
public String getName() { //获取name的值
return name;
}
public void setName(String n) { //设置name的值
name = n;
}
public int getAge() { //获取age的值
return age;
}
public void setAge(int m) { //设置age的值
if(m < 0 || m > 120){ //判断输入的年龄
System.out.println("你输入的年龄有误!");
}else{
age = m;
}
}
public void show(){
System.out.println("姓名是:"+name+",年龄:"+age);
}
}
public class DraftTest {
public static void main(String[] args){
Draft zs = new Draft(); //创建第一个对象
zs. setName("张三"); //使用set方法设置成员变量name的值
zs.setAge(20); //使用set方法设置成员变量age的值
zs.show();
Draft ls = new Draft(); //创建第二个对象
ls.setName("李四"); //使用set方法设置成员变量name的值
ls.setAge(-30); //使用set方法设置成员变量name的值
ls.show();
}
}
姓名是:张三,年龄:20
你输入的年龄有误!
姓名是:李四,年龄:0
这里我们可以看到,负数的年龄已经不能输出了,输出的是int型的默认值0。
三、this关键字的使用
我们上文的代码已经接近完美了,但还没达到
public void setName(String n) { //设置name的值
name = n;
}
public void setAge(int m) { //设置age的值
if(m < 0 || m > 120){ //判断输入的年龄
System.out.println("你输入的年龄有误!");
}else{
age = m;
}
}
通过这段代码我们可以看到,我们传过来的参数没有达到见名知意,比如传过来一个n,我们自己知道是姓名,但别人阅读代码时,还可能会以为是naocan呢。这里我们把他改一下
public class Draft {
private String name;
private int age;
public String getName() { //获取name的值
return name;
}
public void setName(String name) { //设置name的值
name = name;
}
public int getAge() { //获取age的值
return age;
}
public void setAge(int age) { //设置age的值
if(age < 0 || age > 120){ //判断输入的年龄
System.out.println("你输入的年龄有误!");
}else{
age = age;
}
}
public void show(){
System.out.println("姓名是:"+name+",年龄:"+age);
}
}
public class DraftTest {
public static void main(String[] args){
Draft zs = new Draft(); //创建第一个对象
zs. setName("张三"); //使用set方法设置成员变量name的值
zs.setAge(20); //使用set方法设置成员变量age的值
zs.show();
Draft ls = new Draft(); //创建第二个对象
ls.setName("李四"); //使用set方法设置成员变量name的值
ls.setAge(-30); //使用set方法设置成员变量name的值
ls.show();
}
}
这样看来就没问题了,也做到了见名知意,但是——请看运行结果
姓名是:null,年龄:0
你输入的年龄有误!
姓名是:null,年龄:0
发现问题没有,输出的全部都是属性数据类型的默认值。
因为:在同一个类中,成员变量和局部变量同名时,局部变量具有更高的优先级
在方法的参数列表中的参数,也是局部变量
所以我们方法体中的"name = name","age = age"都是局部变量,我们的定义的属性name和age是成员变量,它们并没有被赋值,而我们show()方法里是成员变量name和成员变量age,所以当我们调用show()方法时,控制台输出的是数据类型的默认值。
难道这种写法行不通吗?当然行的通,不然我写它干嘛,下面有请this关键字登场
语法格式:
this.变量名;
this修饰的变量用于指代成员变量(哪个变量有this修饰,哪个就是成员变量)
public class Draft {
private String name;
private int age;
public String getName() { //获取name的值
return name;
}
public void setName(String name) { //设置name的值
this.name = name;
}
public int getAge() { //获取age的值
return age;
}
public void setAge(int age) { //设置age的值
if(age < 0 || age > 120){ //判断输入的年龄
System.out.println("你输入的年龄有误!");
}else{
this.age = age;
}
}
public void show(){
System.out.println("姓名是:"+name+",年龄:"+age);
}
}
public class DraftTest {
public static void main(String[] args){
Draft zs = new Draft(); //创建第一个对象
zs. setName("张三"); //使用set方法设置成员变量name的值
zs.setAge(20); //使用set方法设置成员变量age的值
zs.show();
Draft ls = new Draft(); //创建第二个对象
ls.setName("李四"); //使用set方法设置成员变量name的值
ls.setAge(-30); //使用set方法设置成员变量name的值
ls.show();
}
}
姓名是:张三,年龄:20
你输入的年龄有误!
姓名是:李四,年龄:0
这样一来,我们的代码实现就没有问题了
什么时候用this关键字?
当局部变量与成员变量重名的时候,用this关键字来修饰成员变量
this关键字与对象的关系:
this:代表所在类的对象引用 (方法被哪个对象调用,this就代表哪个对象)
四、封装
面向对象的三大特征:封装、继承、多态
什么是封装(封装的定义):
把对象的所有组成部分组合在一起,封装定义程序如何引用对象的数据,封装实际上是使用方法将类的数据隐藏起来,控制用户对类的修改和访问数据的程度。适当的封装可以让程序代码更容易理解和维护,也加强了程序代码的安全性。
封装的原则:
将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问private修饰的成员变量,提供对应的getXxx()/setXxx()方法。
其实封装大家已经学会了,就是我们上面的代码,下面我们再来看一下完整代码
public class Draft {
private String name;
private int age;
public String getName() { //获取name的值
return name;
}
public void setName(String name) { //设置name的值
this.name = name;
}
public int getAge() { //获取age的值
return age;
}
public void setAge(int age) { //设置age的值
if(age < 0 || age > 120){ //判断输入的年龄
System.out.println("你输入的年龄有误!");
}else{
this.age = age;
}
}
public void show(){
System.out.println("姓名是:"+name+",年龄:"+age);
}
}
public class DraftTest {
public static void main(String[] args){
Draft zs = new Draft(); //创建第一个对象
zs. setName("张三"); //使用set方法设置成员变量name的值
zs.setAge(20); //使用set方法设置成员变量age的值
zs.show();
Draft ls = new Draft(); //创建第二个对象
ls.setName("李四"); //使用set方法设置成员变量name的值
ls.setAge(-30); //使用set方法设置成员变量name的值
ls.show();
}
}
关于封装的学习就到这了,从上到下一遍过,就是那么丝滑。好了,今天的学习到此就结束了,我是一米八、有腹肌、低于半小时你报警的Loveletter,觉得内容不错的小伙伴可以点点关注,我们下篇博文见,再见!