本篇会加入个人的所谓‘鱼式疯言’
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
???可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!
前言
小伙伴们有了解过面向对象的三大特性吗?
分别是:封装,继承,多态。
接下来的文章小编讲带着大家重点理解 封装,继承,多态 。
而在本篇文章中小编讲解的就是我们面向对象的第一式: 封装
目录
封装封装扩展之包访问限定符static 成员代码块一. 封装
1. 封装的概念
面向对象程序三大特性:封装、继承、多态。
而类和对象阶段,主要研究的就是封装特性。何为封装呢?
简单来说
就是 套壳屏蔽细节。
比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等
让用户来和计算机进行交互,完成日常事务。
但实际上:电脑真正工作的却是CPU、显卡、内存等一些硬件元件。
对于计算机使用者而言,不用关心 内部核心部件,比如主板上线路是如何布局的,CPU内部是如何设计的等…
用户只需要知道,怎么开机、怎么通过键盘和鼠标与计算机进行交互即可。因此 计算机厂商在出厂时,在外部套上壳
子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘插孔等,让用户可以与计算机进行交互即可。
这时小伙伴应该就可以引出咱封装的概念了吧 ! ! !
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行 交互
但在谈及封装的理解之前,小编就不得不先介绍一下我们的封装扩展的包 的概念了 ? ? ?
二. 封装扩展之包
这时小爱同学又蒙圈了了,啥是包呢,为啥我们了解封装之前要提及包的概念呢 ? ? ?
小伙伴们不妨先带着这些疑问来慢慢和小编一起探讨吧 ❤️ ❤️ ❤️
1. 包的概念
在面向对象体系中,提出了一个软件包的概念,
即:为了更好的管理类,把多个类收集在一起成为一组,称为 软件包。
有点类似于 目录 。
比如:为了更好的管理电脑中的歌曲,一种好的方式就是将相同属性 的歌曲放在相同文件下
也可以对某个文件夹下的音乐进行更详细的分类。
在Java中也引入了包,包是对类、接口等的封装机制的体现,是一种对类或者接口等的很好的组织方式,
比如:一个包中的类不想被其他包中的类使用。
包还有一个重要的作用:在同一个工程中允许存在相同名称的类,只要处在不同的包中即可。
举个栗子
Java 中已经提供了很多 现成的类 供我们使用.
例如 Date类:可以使用 java.util.Date 导入 java.util 这个包中的 Date类.
class Test { public static void main(String[] args) { java.util.Date date = new java.util.Date();// 得到一个毫秒级别的时间戳 System.out.println(date.getTime()); }}
但是这种写法比较麻烦一些, 可以使用 import 语句导入包.
import java.util.Date;class Test { public static void main(String[] args) { Date date = new Date();// 得到一个毫秒级别的时间戳 System.out.println(date.getTime()); }}
如果需要使用 java.util 中的其他类, 可以使用 import java.util.
import java.util.*;class Test { public static void main(String[] args) { Date date = new Date();// 得到一个毫秒级别的时间戳 System.out.println(date.getTime()); }}
鱼式疯言
但是小编更建议 显式的指定要导入的类名. 否则还是容易出现冲突的情况.
import java.util.*;import java.sql.*;public class Test { public static void main(String[] args) {// util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错 Date date = new Date(); System.out.println(date.getTime()); }// // 编译出错// Error:(5, 9) java: 对Date的引用不明确// java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配}
在这种情况下需要使用完整的类名
import java.util.*;import java.sql.*;public class Test {public static void main(String[] args) {java.util.Date date = new java.util.Date();System.out.println(date.getTime());}}
2.自定义包
<1>基本规则
在文件的最上方加上一个 package 语句指定该代码在哪个包中.
包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.bit.demo1 ).
包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存储 代码.
如果一个类没有 package 语句, 则该类被放到一个默认包中.
小伙伴应该都是用 IDEA 吧,那具体怎么操作呢,
还没下载 IDEA 的小伙伴可以点开下面链接学习安装哦
IEDA安装教程
<2>. 具体操作步骤
在 IDEA 中先新建一个包: 右键 src -> 新建 -> 包 在弹出的对话框中输入包名,例如 com.bit.demo1 在包中创建类, 右键包名 -> 新建 -> 类, 然后输入类名即可. 此时可以看到我们的磁盘上的目录结构已经被 IDEA 自动创建出来了 同时我们也看到了, 在新创建的 Test.java 文件的最上方, 就出现了一个 package 语句
<3>. 常见的包
java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
java.lang.reflect:java 反射编程包;
java.net:进行网络编程开发包。
java.sql:进行数据库开发的支持包。
java.util:是java提供的工具程序包。(集合类等) 非常重要
java.io:I/O编程开发包。
鱼式疯言
这些常见的包友友们不需要特别记忆,只要会用就可以了 ❤️ ❤️ ❤️
三. 访问限定符
1. 基本概念
Java中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合人类对事物的认
知
而访问权限用来控制方法或者字段能否直接在类外使用。Java中提供了四种访问限定符:
比如:
public:可以理解为一个人的 外貌特征, 谁都可以看得到
default: 对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是 隐私 了
private:只有 自己知道,其他人都不知道
鱼式疯言
补充说明:
protected主要是用在继承中,继承部分详细介绍
default 权限指:什么都不写时的默认权限
访问权限除了可以限定类中成员的可见性,也可以控制类的可见性
class Computer { private String cpu; // cpu private String memory; // 内存 public String screen; // 屏幕 String brand; // 品牌---->default属性 public Computer(String brand, String cpu, String memory, String screen) { this.brand = brand; this.cpu = cpu; this.memory = memory; this.screen = screen; } public void Boot(){ System.out.println("开机~~~"); } public void PowerOff(){ System.out.println("关机~~~"); } public void SurfInternet(){ System.out.println("上网~~~"); }}class TestComputer { public static void main(String[] args) { Computer p = new Computer("HW", "i7", "8G", "13*14"); System.out.println(p.brand); // default属性:只能被本包中类访问 System.out.println(p.screen); // public属性: 可以任何其他类访问// System.out.println(p.cpu); // private属性:只能在Computer类中访问,不能被其他类访问 }}
注意:一般情况下成员变量设置为private,成员方法设置为 public。
下面就让小编带着大家具体了解下 public private default 吧
2. public 限定符
public 修饰下作用范围: 全体范围
<1>. 举个栗子
package Testdmo1;import Testdmol2.U;public class J3_12two { public static void main(String[] args) { U u=new U(); System.out.println(u.age); }}
package Testdmol2;public class U {public int age=10;}
由此 public 修饰的
我们可以得出在任意包下我们都可以访问
3. private 限定符
private 修饰下作用范围: 同一个包中的同一个类
<1>. 栗子one
package Testdmo1;import Testdmol2.U;public class J3_12two { public static void main(String[] args) { U u=new U(); System.out.println(u.age); }}
package Testdmol2;public class U {private int age=10;}
小伙伴也都看到了
很明显我们 private 修饰的 成员变量 是无法直接访问和修改的
如果要访问就没办法了么?
办法还是有的,那该怎么办呢。
我们可以用方法来传参的方法来 间接的访问
<2>. 栗子two
比如:
package Testdmol2;public class U {private int age=10; public int getAge() { return age; } public void setAge(int age) { this.age = age; }}
package Testdmo1;import Testdmol2.U;public class J3_12two { public static void main(String[] args) { U u=new U(); System.out.println(u.getAge()); }}
是的,我们可以方法来访问和修改内部成员变量的值 ! ! !
写到这里我们算正式 接触封装 了
鱼式疯言
总结一下封装的条件:
private 修饰需要 写方法 来修改和访问在这里小编有个技巧来写 封装方法,宝子们可以学下哦 ! ! !
<3>. 实用操作步骤
在当前类下鼠标右击点生成 生成中点击 Getter 和 Setter 点击年龄 并确定即可即可生成我们的 封装方法 ! ! !
3. default 限定符
public 修饰下作用范围:
同一个包中的同一类 同一个包中的不同类package Testdmo1;import Testdmol2.U;public class J3_12two { public static void main(String[] args) { U u=new U(); System.out.println(u.age); }}
package Testdmol2; class U {int age=10;}
这里也就差不多讲解 完毕了。
如果我要在不同包下访问和修改我们 fault 修饰的成员变量,仍然是需要封装方法来修改和访问的。
鱼式疯言
fault 只有在相同包才能使用哦,
不同的包是不能使用的哦 (除非使用封装方法)
有小伙伴问了不是还有 protected 吗
这个得等下一篇我们的面向对象第二式: 继承
小编会带着大家重点说明这个修饰符 ? ? ?
四. static 成员
static 不是静态的吗? 和我们的类有什么关系呢 ? ? ?
下面就让小编带着大家来看看吧
1. static 的引入
使用前文中介绍的学生类实例化三个对象s1、s2、s3。
每个对象都有自己特有的名字、性别,年龄,学分绩点等成员信息,这些信息就是对不同学生来进行描述的,如下所示:
class Student{ // ... public static void main(String[] args) { Student s1 = new Student("Li leilei", "男", 18, 3.8); Student s2 = new Student("Han MeiMei", "女", 19, 4.0); Student s3 = new Student("Jim", "男", 18, 2.6); }}
假设三个同学是同一个班的,那么他们上课肯定是在同一个教室
那既然在同一个教室,那能否给类中再加一个成员变量,来保存同学上课时的教室呢?
答案是不行的。
比如下面这样:
之前在 Student类中定义的成员变量,每个对象中都会包含一份(称之为实例变量) ,因为需要使用这些信息来描述
具体的学生。
而现在要表示学生上课的教室,这个教室的属性并不需要每个学生对象中都存储一份,而是需要让所有的学生来共享。
在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的。
鱼式疯言
具体使用场景
当我们要保存一份数据怎么办,static 修饰的就可以做到 ! ! !
下面小伙伴们都来具体熟悉下我们 static 修饰的成员变量吧
2.static修饰成员变量
static修饰的成员变量,称为静态成员变量,
静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的。
<1>. 举个栗子
class Student { public String name; public String gender; public int age; public double score; public static String classRoom = "Bit306"; public Student(String name, String gender, int age, double score) { this.name = name; this.gender = gender; this.age = age; this.score = score; } // ... public static void main(String[] args) {// 静态成员变量可以直接通过类名访问 System.out.println(Student.classRoom); Student s1 = new Student("Li leilei", "男", 18, 3.8); Student s2 = new Student("Han MeiMei", "女", 19, 4.0); Student s3 = new Student("Jim", "男", 18, 2.6);// 也可以通过对象访问:但是classRoom是三个对象共享的 System.out.println(s1.classRoom); System.out.println(s2.classRoom); System.out.println(s3.classRoom); }}
小伙伴可以以 调试 方式运行上述代码
(如果有不会调试的小伙伴可以参考小编下面的链接中有调试技巧哦)
调试技巧链接
然后在监视窗口中可以看到
静态成员变量 并没有存储到某个具体的 对象 中。
鱼式疯言
总结一下
静态成员变量的特性有:
不属于某个具体的对象,是 类的属性 ,所有对象共享的,不存储在某个对象的空间中 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问 类变量 存储在方法区当中 生命周期伴随类的一生(即:** 随类的加载而创建 ,随类的卸载而销毁 **)3. static 修饰成员方法
一般类中的数据成员都设置为 private,而成员方法设置为 public
那设置之后,Student类 中 classRoom属性 如何
在类外访问呢?
<1>. 栗子one
public class Student{private String name;private String gender;private int age;private double score;private static String classRoom = "Bit306";// ...}public class TestStudent {public static void main(String[] args) {System.out.println(Student.classRoom);}}//编译失败://Error:(10, 35) java: classRoom 在 extend01.Student 中是 //private 访问控制
那么问题来了,这个 private + static 该怎么访问呢 ? ? ?
Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。
静态成员一般是通过静态方法来访问的。
由此我们可以得出以下结论
静态方法特性:
不属于某个具体的对象,是类方法 可以通过对象调用,也可以通过类名.静态方法名(…)方式调用,更推荐使用后者 不能在静态方法中访问任何 非静态成员变量<2>. 栗子two
static String getClassRoom(){ System.out.println(this); return classRoom;}// 编译失败:Error:(35, 28) java: 无法从静态上下文中引用非静态 变量 thisstatic String getClassRoom(){ age += 1; return classRoom;}// 编译失败:Error:(35, 9) java: 无法从静态上下文中引用非静态 变量 age
静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递 this引用 public static String getClassRoom(){doClass();return classRoom;}// 编译报错:Error:(35, 9) java: 无法从静态上下文中引用非静态 方法 doClass()
静态方法无法重写,不能用来实现多态 (此处大家暂时不用管,后序多态位置详细讲解)。 4. static 成员变量初始化
注意:静态成员变量一般不会放在 构造方法 中来初始化,构造方法中初始化的是与 对象 相关的实例属性
那我们该怎么初始化呢 ? ? ?
有问题就会有解决方案
静态成员变量的初始化分为两种:就地初始化 和 静态代码块初始化。
<1>.方案一 :就地初始化
就地初始化指的是:在定义时直接给出初始值
public class Student{private String name;private String gender;private int age;private double score;private static String classRoom = "Bit306";// ...}
<2>.方案二: 静态代码块初始化
那什么是代码块呢?
小伙伴们不妨继续往后看 ? ~~~
五.代码块
1. 代码块概念及分类
使用{} 定义的一段代码称为代码块。
根据代码块定义的位置以及关键字,又可分为以下四种:
普通代码块构造块静态块同步代码块(后续讲解多线程部分再谈)2. 普通代码块
普通代码块:定义在方法中的代码块.
public class Main{public static void main(String[] args) {{ //直接使用{}定义,普通方法块int x = 10 ;System.out.println("x1 = " +x);}int x = 100 ;System.out.println("x2 = " +x);}}
但这种用法较少见
3. 构造代码块
构造块:定义在类中的代码块 (不加修饰符) 。
也叫:实例代码块。构造代码块一般用于初始化实例成员变量。
public class Student{//实例成员变量private String name;private String gender;private int age;private double score;public Student() {System.out.println("I am Student init()!");}//实例代码块{this.name = "bit";this.age = 12;this.sex = "man";System.out.println("I am instance init()!");}public void show(){System.out.println("name: "+name+" age: "+age+" sex: "+sex);}}public class Main {public static void main(String[] args) {Student stu = new Student();stu.show();}}
4.静态代码块
使用 static 定义的代码块称为 静态代码块 。
一般用于初始化静态成员变量。
class Student{ private String name; private String gender; private int age; private double score; private static String classRoom; //实例代码块 { this.name = "bit"; this.age = 12; this.gender = "man"; System.out.println("I am instance init()!"); } // 静态代码块 static { classRoom = "bit306"; System.out.println("I am static init()!"); } public Student() { System.out.println("I am Student init()!"); } public static void main(String[] args) { Student s1 = new Student(); System.out.println(Student.classRoom); System.out.println("==========="); Student s2 = new Student(); }}
由上面的代码执行结果显示
从中我们可以得出一下结论:
静态代码块 无论生成多少对象 ,只执行一次,而我们的 实例代码块 只有在创建对象时才会被执行
静态是最先被执行的 ,具体执行顺序可以参考以下这张图
静态代码块中的如果有成员方法是可以被修改的(上图可知)
静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
总结
封装: 了解了封装的基本含义 封装扩展之包: 内部包和自定义的不同使用方法 访问限定符: 具体讲解了三种不同的限定符,并通过限定符对我们的类成员进行封装处理 static 成员: 理解静态的本质以及对于静态成员方法和变量的使用场景 代码块: 重点梳理了我们三种不同代码的特别以及优先顺序如果觉得小编写的还不错的咱可支持 三连 下 (定有回访哦) , 不妥当的咱请评论区 指正
希望我的文章能给各位宝子们带来哪怕一点点的收获就是 小编创作 的最大 动力 ? ? ?