【JavaSE系列】第七话 —— 类和对象(2)
这篇博客承接于上一篇博客:【JavaSE系列】第七话 —— 类和对象(1)
🚗目录🚗
🚓七、封装
🚕🚕7.1 封装的概念
🛺🛺7.2 访问修饰限定符
🚙八、static成员
🚌🚌8.1 再谈Student类
🚐🚐8.2 static修饰成员变量
🚎🚎8.3 static修饰成员方法
🚑🚑8.4 static还需要注意的地方
🚒🚒🚒注意一
🚚🚚🚚注意二
🚛🚛8.5 static成员变量初始化
🚜🚜🚜8.5.1 就地初始化
🚘🚘🚘8.5.2 静态代码块初始化
🚍九、代码块
🦽🦽9.1 代码块概念 以及分类
🦼🦼9.2 普通代码块
🛹🛹9.3 构造代码块
🚲🚲9.4 静态代码块
🛫十、内部类
🪂🪂10.1 实例内部类
🚁🚁🚁10.1.1 什么是 实例内部类
🚀🚀🚀10.1.2 如何去实例化内部类对象
⛵⛵⛵10.1.3 实例内部类当中 不能定义 静态的成员变量
💺💺💺10.1.4 实例内部类当中,成员变量和外部类成员变量重名
🛬🛬🛬10.1.5 实例内部类 所演示的代码
🏯10.2 静态内部类
🚢🚢🚢10.2.1 什么是 静态内部类
🗼🗼🗼10.2.2 如何实例化静态内部类
🏰🏰🏰10.2.3 如何去访问静态内部类
🌉🌉🌉10.2.4 静态内部类 所演示的代码
🛸🛸🛸10.3 匿名内部类
🌁总结
七、封装
7.1 封装的概念
面向对象程序 三大特性(注意 是三大特性,而不是三个特性,可能还有第四个,第五个,......,第n个特性):封装、继承、多态;
而 类和对象阶段,主要研究的就是 封装 特性;
那么什么是封装呢?简单来说就是 套壳屏蔽细节。
举个小例子来说明一下 到底什么是封装:
比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等等,让用户来和计算机进行交互,完成日常事务;
但实际上,电脑正真工作的却是CPU、显卡、内存等一些硬性原件;
对于计算机使用者而言,不用关心 内部核心部件,比如主线板上线路是如何布局的,CPU内部是如何设计的等等,他们只需要知道,怎么去开关机、怎么通过键盘和鼠标 与计算机进行交互即可;
因此 计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘、插孔等等,让用户可以与计算机进行交互即可。
封装:将数据和操作数据的方法进行有机结合,隐藏 对象的属性和实现细节,仅对外公开接口来和对象进行 交互。
7.2 访问修饰限定符
那么,应该怎么样对 数据以及操作数据的方法 来进行封装呢?
这就涉及到了四个访问修饰限定符:public、private、protected、default 。
这个知识点博主把单独分享了出来,
大家感兴趣的话,可以点击下面的传送:
传送门正在建造中......
建造进度(80%)......
八、static成员
8.1 再谈Student类
首先创建对象student1、student2,并且每个对象都有各自的 name、age、score等信息,来对不同的对象进行描述的:
public class Student { //...... public String name; public int age; public double score; public String classes; //...... public static void main(String[] args) { Student student1 = new Student("bit",18,100); Student student2 = new Student("张三",19,100);}
那么,通过打断点的形式,我们可以知道 每个对象所存储的数据:
假设三个同学是同一个班的,即:在同一间教室上课,那么有没有一种办法,可以同时来保存他们在同一间教室上课这个信息呢......
在Student类中定义的成员变量,每个对象中都会包含一份,应为需要使用这些信息来描述具体的学生;
而现在要表示学生上课的教室,这个教室的属性 并不需要每个学生对象中都存储一份,而是让每一位学生所共享的;
在Java中,被static修饰的成员,称之为 静态成员(类成员),其不属于某一个具体的对象,而是所有的对象所共享的。
8.2 static修饰成员变量
static修饰的成员变量,称为 静态成员变量;
静态成员变量 的最大特性:不属于某个具体的对象,是所有对象所共享的。
所以,如果我们想要访问该静态成员变量的话,不需要new一个对象,
可以直接用 类名.静态成员变量 来进行访问:
上面的整体代码是这个样子的:
class Student{ public String name; public int age; public double score; public static String classes; public Student(String name, int age, double score) { this.name = name; this.age = age; this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + ", 班级=" + classes + '}'; }}public class TestDemo { public static void main(String[] args) { Student student1 = new Student("bit",18,90); Student student2 = new Student("张三",20,100); Student.classes = "Java"; System.out.println(student1); System.out.println(student2); }}
静态成员变量 不建议 通过 对象名.静态成员变量 来进行访问(这样写是合法不合理的):
【静态成员变量的静态属性】
- 不属于某个具体的对象,是类的属性,所有对象所共享的,不存储在某个对象的空间中;
- 即可以通过对象访问,也可以通过类名访问,不过一般更加推荐使用类名访问(通过对象访问 就像是那个 合法但是不合理);
- 静态成员变量(类变量) 存储在方法区中;
- 生命周期伴随类的一生(即:随类的创建而创建,随类的销毁而销毁)。
8.3 static修饰成员方法
一般类中的数据成员 都设置为private,而成员方法设置为public;
那设置之后,Student类中的classes属性 如何在类外访问呢?
那static属性应该如何去访问呢?
Java中,被static修饰的成员方法 称为 静态成员方法,是类的方法,不是某个对象所特有的;
此时,我们可以用 类名.classes来进行访问:
这个是完整的代码示例:
class Student{ public String name; public int age; public double score; public static String classes; public Student(String name, int age, double score) { this.name = name; this.age = age; this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + ", 班级=" + classes + '}'; } public static void func(){ System.out.println("这个是一个静态的成员方法!!!!!!"); }}public class TestDemo { public static void main(String[] args) { Student.func(); }}
【静态方法特性】
- 不属于某个具体的对象,是类方法;
- 可以通过对象调用,也可以通过 类名.静态方法名(......) 方式调用,当然,也还是更推荐使用 类名.静态方法名(......) 来调用,通过对象调用 就是“合法但是不合理”;
- 静态方法 没有隐藏的this引用参数,因此不能在静态方法中 访问任何非静态成员变量;
- 静态方法中不能调用 任何非静态方法,因为非静态方法有this参数,在静态方法中 调用时无法传递this引用。
8.4 static还需要注意的地方
注意一:
class Student{ public String name; public int age; public double score; public static String classes; public static void func(){ System.out.println("这个是一个静态的成员方法!!!!!!"); }}public class TestDemo { public static void main(String[] args) { Student student1 = null; student1.classes = "Java"; System.out.println(student1.classes); }}
如果没有看编译结果的话,很多人的第一反应是:会发生空指针异常;
但是,正确的编译结果是:
其实原因是这样的:
在实际生活中,我们也不会这样去访问的(这样是合法不合理的),乖乖的用类名去访问就可以了。
【总结】静态的成员变量 和 静态的成员方法,都不依赖于对象;因为他们是类变量。
注意二:
在普通的方法里面 加上 静态成员变量(或成员方法,这里只列了成员变量的例子),观察是否可以访问:
这个可以访问的原因:
要调用doClass()方法的前提是:先前需要实例化出一个对象student;
所以可以调用。
在静态的成员方法 里面加上 普通的成员变量(或成员方法,这里只列了成员变量的例子),观察是否可以访问:
//注意二所使用的代码:class Student{ public String name; public int age; public double score; public static String classes; public Student(String name) { this.name = name; } public static void func(){ //System.out.println("这个是一个静态的成员方法!!!!!!" + name); } public void doClass(){ System.out.println(this.name + "正在上课!"+" 班级:"+classes); }}public class TestDemo { public static void main(String[] args) { Student.classes = "Java"; Student student = new Student("张三"); student.doClass(); }}
原因很简单:
在调用 func()方法的时候,没有实例化出一个对象(对于name这些普通成员变量来说,一定是要依赖于对象的,即:想要访问name,必须要有一个对象) 。
【总结】静态的不依赖于对象,非静态的依赖于对象。
所以,有static的必须要用new一个对象,这就解释了为什么一开始在写主函数的时候,是要这样写的:
8.5 static成员变量初始化
【注意】静态成员变量 一般不会放在构造方法中来初始化,构造方法中初始化的是 与对象相关的实例属性;
静态成员变量的初始化分为两种:就地初始化 和 静态代码块初始化。
8.5.1 就地初始化
就地初始化 指的是:在定义时直接给出初始值:
class Student{ public String name; public int age; public double score; public static String classes = "Java"; //......}
8.5.2 静态代码块初始化
在学习这一部分内容的时候,还是需要来介绍一下什么是代码块......
九、代码块
9.1 代码块概念 以及分类
使用 {} 定义的一段代码称为代码块。
根据代码块定义的位置 以及关键字,又可分为以下四类:
- 实例代码块 / 构造代码块;
- 静态代码块;
- 本地代码块 / 普通代码块(用不到);
- 同步代码块(目前用不到)。
9.2 普通代码块
普通代码块:定义在方法中的代码块:
9.3 构造代码块
构造代码块:定义在类中的代码块(不加修饰符),也叫:实例代码块。
class Student2 { public String name; public int age; public double score; public Student2(String name, int age, double score) { this.name = name; this.age = age; this.score = score; System.out.println("调用带有3个参数的构造方法!"); } { System.out.println("实例代码块!!!!!!"); } public static void main(String[] args) { Student2 student = new Student2("张三",19,100); }}
9.4 静态代码块
使用static定义的代码块 称为静态代码块;
一般用于初始化静态成员变量。
【注意】如果有多个静态代码块,那么执行的顺序和定义的顺序有关;定义在后面的 静态代码块 会把 定义在前面的 给覆盖掉(当然,只是赋值覆盖,就相当于把两个 静态代码块连起来,然后去覆盖,像打印的就不会覆盖了):
class Student2 { public String name; public int age; public double score; public static String classes; public Student2(String name, int age, double score) { this.name = name; this.age = age; this.score = score; System.out.println("调用带有3个参数的构造方法!"); } @Override public String toString() { return "Student2{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + ",班级= " + classes + '}'; } { System.out.println("实例代码块!!!!!!"); } static { classes = "Java_1"; System.out.println("静态代码块!!!!!!"); } static { classes = "Java_2"; System.out.println("静态代码块!!!!!!"); } public static void main(String[] args) { Student2 student = new Student2("张三",19,100); System.out.println(student); System.out.println("============================================"); Student2 student2 = new Student2("李四",19,100); System.out.println(student2); }}
十、内部类
内部类也是一种类,其重点在于内部二字;
在一个类的内部 定义的类,叫做 内部类。
内部类 可以分为以下几种:
- 实例内部类;
- 静态内部类;
- 匿名内部类。
所以说,以后 如果说内部类的时候,需要带上前缀(不同的内部类,性质、使用方式等等都是有区别的)。
10.1 实例内部类
10.1.1 什么是 实例内部类
class OuterClass { //普通成员变量(实例成员变量) public int data1 = 10; private int data2 = 20; public static int data3 = 30; class InnerClass { //class InterClass 这个类就叫做 实例内部类 }}
10.1.2 如何去实例化内部类对象
//外部类名.内部类名 变量 = 外部类对象的引用.new 内部类名();
10.1.3 实例内部类当中 不能定义 静态的成员变量
原因:内部类InnerClass需要 外部类对象 才能够进行实例化的,如果里面有 静态static,那么data6就不需要外部类对象。
当然,也不可以含有静态方法,大家可以自己去试一试:
如果要定义,必须是 编译的时候就要确定的值(即:必须是 static finna的)(内部类里面内部类里面内部类里面):
如果实在内部类外面定义,那就肯定是编译错误:
10.1.4 实例内部类当中,成员变量和外部类成员变量重名
那么,就会优先使用 内部类(自己)的:
那么,如何去调用 外部类的data1呢?
10.1.5 实例内部类 所演示的代码
class OuterClass { //普通成员变量(实例成员变量) public int data1 = 10; private int data2 = 20; public static int data3 = 30; /** * 实例内部类 */ class InnerClass { public int data1 = 1000; public int data4 = 40; public int data5 = 50; public static final int data6 = 60;//常量-》编译的时候,就已经确定这个值是几了 //内部类里面不可以有静态方法// public static void funcStatic(){//// } public InnerClass(){ System.out.println("InnerClass的构造方法!!!!!!"); } public void method(){ System.out.println("Java:"+OuterClass.this.data1); System.out.println(data2); System.out.println(data3); System.out.println(data4); System.out.println(data5); System.out.println(data6); System.out.println("InnerClass的一个method方法!!!!!!"); } } public void methodOut(){ //static final int c = 10; }}public class TestDemo { public static void main(String[] args) { OuterClass outerClass = new OuterClass(); OuterClass.InnerClass innerClass = outerClass.new InnerClass(); innerClass.method(); } public static void main1(String[] args) { OuterClass outerClass = new OuterClass(); System.out.println(outerClass.data1); //外部类名.内部类名 变量 = 外部类对象的引用.new 内部类名(); OuterClass.InnerClass innerClass = outerClass.new InnerClass(); OuterClass.InnerClass innerClass1 = new OuterClass().new InnerClass(); //new OuterClass():匿名对象:一般在使用1次的时候(每一次使用都要new一个对象)// System.out.println(new OuterClass().data1);// System.out.println(new OuterClass().data2); }}
10.2 静态内部类
10.2.1 什么是 静态内部类
被static修饰的内部类叫做 静态内部类。
class OuterClass2 { public int data1 = 10; private int data2 = 20; public static int data3 = 30; static class InnerClass { //这个类就叫做静态内部类 }}
10.2.2 如何实例化静态内部类
//外部类名.静态内部类名 变量 = new 外部类名.静态内部类名
10.2.3 如何去访问静态内部类
在静态内部类当中,只能访问外部类的静态的成员:
如果要访问外部类的非静态成员,那么高怎么去访问呢?
——去提供外部类对象:
去访问方法的时候也是一样的,这里就不演示了。
10.2.4 静态内部类 所演示的代码
class OuterClass2 { public int data1 = 10; public int data2 = 20; public static int data3 = 30; public void method() { System.out.println("OuterClass2::method()"); } static class InnerClass { //这个类就叫做静态内部类 public int data4 = 40; private int data5 = 50; public static int data6 = 60; OuterClass outerClass = new OuterClass(); public InnerClass() { System.out.println("InnerClass的构造方法!!!!!!"); } public void method() { System.out.println(outerClass.data1); System.out.println(outerClass.data2); System.out.println(data3); System.out.println(data4); System.out.println(data5); System.out.println(data6); System.out.println("innerclass的method的方法!!!!!!"); } }}public class TestDemo2 { public static void main(String[] args) { //调用的时候不需要外部类对象,所以 静态内部类使用的频率会比较多一点 OuterClass2.InnerClass innerClass = new OuterClass2.InnerClass(); }}
10.3 匿名内部类
这部分内容等到后面 接口 的内容再详细介绍嗷......
传送门正在建造中......
建造进度(0%)......
总结
花费了好几天的时间总结了关于 类与对象 的知识 到此就结束了;
当然,还有一些不足的地方;
后期也要修修改改;
希望大家收获满满呀!!!!!!
如果铁铁们可以一键三连那就更棒了,特别特别感谢 ୧(๑•̀⌄•́๑)૭ 。