Java|谈谈java中封装的那点事

目录
前言
什么是封装
包访问权限又是什么
什么是静态成员


前言 Hello,各位铁汁们大家好呀!我是小儿,上篇博客我们讲了java中的构造函数和this关键字,不知道大家理解的怎么样?今天让我们继续学习,谈谈封装的那点事
Java|谈谈java中封装的那点事
文章图片

什么是封装 什么是封装呢?我们先来看一段代码

class Student { public String name; private int age; } public class Test4 { public static void main(String[] args) { // 引用变量student指向该新创建的对象 Student student = new Student(); // 实例化对象 student.age = 12; // 通过引用变量名.成员变量来访问Student类中的成员变量 } }


让我们运行一下
Java|谈谈java中封装的那点事
文章图片


好家伙,报错了,为什么当age被private修饰后就不能访问了呢?
private的字面意思就是私人的、私有的,在java中被private修饰的变量只能在当前类中访问,就像上面的Student类中的age变量,它就只能在Student这个类中被访问,不能在Test4这个类中访问。
这样有什么用呢?当然有用
Java|谈谈java中封装的那点事
文章图片


这样可以防止age其他地方被随意的修改,比如把age赋值成一个负数,那合适吗、正常吗?
那name成员变量前的public又是什么意思呢?public就是公共的、公开的,被public修饰的成员变量不管在那都是可以被访问的。我们之前在定义成员变量时,好像在变量前没有像public、private这样的东东呀!那时我们也能通过对象引用一个一个的访问那些成员变量呀?
Java|谈谈java中封装的那点事
文章图片

这时我们就有必有引入封装这个概念了

封装将类的某些信息隐藏在类内部,不允许外部程序直接访问,只能通过该类提供的方法来实现对隐藏信息的操作和访问。例如:一台计算机内部极其复杂,有主板、CPU、硬盘和内存, 而一般用户不需要了解它的内部细节,不需要知道主板的型号、CPU 主频、硬盘和内存的大小,于是计算机制造商将用机箱把计算机封装起来,对外提供了一些接口,如鼠标、键盘和显示器等,这样当用户使用计算机就非常方便。
封装的特点:
  • 只能通过规定的方法访问数据。
  • 隐藏类的实例细节,方便修改和实现。

实现封装的具体步骤如下:
  1. 修改属性的可见性来限制对属性的访问,一般设为 private。
  2. 为每个属性创建一对赋值(setter)方法和取值(getter)方法,一般设为 public,用于属性的读写。
  3. 在赋值和取值方法中,加入属性控制语句(对属性值的合法性进行判断)。
Java|谈谈java中封装的那点事
文章图片


我们刚才提到的private其实就是一种封装,被private修饰的只能本类才能访问,其他类都访问不了,如此就对信息进行了隐藏。
那么我们如何访问被private修饰的成员变量呢?
如果外界想要访问私有属性,需要提供一些使用public修饰的公有方法。其中包括用于获取属性值的getXxx方法和设置属性值的setXxx方法
class Student { public String name; private int age; public int getAge() {// 这些专门用来访问设置属性的方法一般用public来修饰 return age; }public void setAge(int age) { this.age = age; } } public class Test4 { public static void main(String[] args) { Student student = new Student(); student.name = "张三"; // 被public修饰的可以在其他类中随意访问(但不太安全,有风险) System.out.println("姓名:" + student.name); System.out.println("======这是分割线========"); student.setAge(19); // 通过专门的设置属性的setAge()方法来赋值(安全,不能随意修改) System.out.println("年龄:" + student.getAge()); //通过专门的访问属性的getAge()来打印 } }


Java|谈谈java中封装的那点事
文章图片

从运行结果来看,姓名、年龄都被成功的赋值并打印了。但因为他们前面的访问修饰限定符不一样,所以对年龄、姓名的访问权限也不同,访问方式自然也不同了。


封装拓展之包 而如果你没任何修饰限定符,编译器默认就是包访问权限;想要理解什么是包访问权限,你首先要理解什么是包。
包的概念 在面向对象体系中,提出了一个软件包的概念,即:为了更好的管理类,把多个类收集在一起成为一组,称为软件 包。
这其实有点类似于我们电脑中不同的文件夹。
Java|谈谈java中封装的那点事
文章图片


在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,比如:一 个包中的类不想被其他包中的类使用。
包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。
我们可以IDEA里尝试创建一个包:
Java|谈谈java中封装的那点事
文章图片


然后输入你包的名字,比如demo1,然后回车
就新创建了一个新的文件夹demo1
Java|谈谈java中封装的那点事
文章图片


在这个文件夹(也就是这个包中)我们就可以添加我们的java文件了
Java|谈谈java中封装的那点事
文章图片


Java|谈谈java中封装的那点事
文章图片

什么是包访问权限
包访问权限就是只要我们再同一个包下面就可以访问互相访问,即使他们不在同一个java文件里面
为了更清楚一点,我们来实践一下
Java|谈谈java中封装的那点事
文章图片


可以看到我们在testdemo1中定义了一个变量a,成员变量a的访问权限是包访问权限
Java|谈谈java中封装的那点事
文章图片

看来只要这个变量是包访问权限,那么在一个包下变量可以互相访问呀!

那么如果不在一个包下呢


【Java|谈谈java中封装的那点事】Java|谈谈java中封装的那点事
文章图片

看来就无法访问了
这下你对包访问权限是否有了一个初步的理解了呢?
从上面的例子我们也不难发现,
  1. 被private修饰的变量只能在同一个类中访问
  2. 默认的包访问权限可以在同一个包下、不同的类中来访问
  3. 而public则是哪都能访问


什么是静态成员 静态成员就是被关键字static修饰的成员变量或者成员方法。
而static又是什么呢?老规矩,先来看一段代码

class Student { private String name; private int age; public String shool; public Student(String name, int age, String shool) {//用构造方法进行初始化 this.name = name; this.age = age; this.shool = shool; System.out.println("姓名:" + this.name + " 年龄:" + this.age + " 学校:" + this.shool); } } public class Test4 { public static void main(String[] args) { Student student1 = new Student("张三", 17, "茶啊二中"); Student student2 = new Student("李四", 16, "茶啊二中"); Student student3 = new Student("王五", 18, "茶啊二中"); } }


Java|谈谈java中封装的那点事
文章图片


可以看出,上面我们创建的三个学生对象都在同一个学校,所以为了节省内存空间,我们其实不需要让创建的每个对象都储存一份学校这个属性,只要有一个内存储存学校这个属性,然后大家共享就好了。
下面先来看共享的一个例子:
class Student { private String name; private int age; public static String school; // 定义一个静态成员变量public Student(String name, int age) { this.name = name; this.age = age; // 想一下我下面为什么不用this.school来访问 System.out.println("姓名:" + this.name + " 年龄:" + this.age + " 学校:" + school); } } public class Test4 { public static void main(String[] args) { // 奇怪吧!我还没实例化对象呢?怎么就能对类中的成员变量赋值呢? Student.shool = "茶啊二中"; Student student1 = new Student("张三", 17); Student student2 = new Student("李四", 16); Student student3 = new Student("王五", 18); } }

Java|谈谈java中封装的那点事
文章图片

什么情况,竟然没报错?
Java|谈谈java中封装的那点事
文章图片

我想你在看了上面的代码,肯定有很多疑惑吧!别着急我们慢慢来揭开static这层神秘的面试
在 Java 中,被 static 修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的 。 如果把shool这个属性设置为static,那school这个静态变量将会单独储存在静态区,而不是和他所在的对象一起存储在堆区。什么意思呢?咱们用图说话: Java|谈谈java中封装的那点事
文章图片


如上图所示,实例化的对象student1和student2共享school这个成员属性。
从上图我们也可以看出静态区的school其实是不依赖对象的,因为他根本都没在对象所在的堆区,所以我们可以直接通过:类名.school来访问这个成员变量。
Java|谈谈java中封装的那点事
文章图片

哈哈,是不是有有点晕。就快完了,加油!

Java|谈谈java中封装的那点事
文章图片

被static修饰的变量称为静态变量,被static修饰的方法称为静态方法
不管静态变量还是静态方法都不属于某个具体的对象,而是整个类的属性。我们下面尝试用一下静态方法,看看他和普通方法的区别在哪里?
Java|谈谈java中封装的那点事
文章图片


可以看出程序在 " run() "这个地方报错了,为啥在静态方法中不能调用普通方法呢?
Java|谈谈java中封装的那点事
文章图片


我们前面说过this这个关键字,其实在这里报错就和this引用有关。我们先来回顾一下this
(?′?`?)(?′?`?)(?′?`?)(?′?`?)(?′?`?)

this的深入:1.在每一个非静态方法的内部,都有一个this,相当于一个句柄,由编译器隐示添加。method(参数列表)可以看成是method(类名 this,参数列表)
在面向对象中,成员属性必须由对象调用,所以在方法内部,每一个成员其实都有一个this.”前缀,当对象调用这个方法的时候,编译器会把该对象传递给方法(也就是常说的“this指向调用该方法的当前对象”),编译器会将其编译为method(对象,实参列表)。

而在一个静态方法内部,由于静态方法是属于类的,被每个类的实例所共享,所以没有this句柄,当然就不能在静态方法中访问非静态的成员(属性和方法),而具体在编译器会怎么看愣,编译器会说哪个对象调用了成员,我都找不到这个对象,然后它就会大吼一句“还有谁!!!”,最后报错。

所以说,静态方法里面调用的必须是不依赖对象的成员变量和成员方法——即静态方法和静态变量,当我们把上面的run普通方法改成静态方法,编译器自然就不报错了。
Java|谈谈java中封装的那点事
文章图片


总结一下:
  • 被static修饰的成员变量或方法,被所有对象所共享
  • 静态变量和静态方法可以直接被类名所调用
  • 静态方法只能调用静态成员,不能调用非静态成员。非静态方法可以调用静态成员,也可以调用非静态成员
好了,以上就们就对静态成员有了一个初步的认识。
各位铁汁们,咱们下篇再见
Java|谈谈java中封装的那点事
文章图片



    推荐阅读