☕导航小助手☕
七、封装
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 匿名内部类
总结
这篇博客承接于上一篇博客:
【JavaSE系列】第七话 —— 类和对象(1)_哎呀是小张啊的博客-CSDN博客
面向对象程序 三大特性(注意 是三大特性,而不是三个特性,可能还有第四个,第五个,......,第n个特性):封装、继承、多态;
而 类和对象阶段,主要研究的就是 封装 特性;
那么什么是封装呢?简单来说就是 套壳屏蔽细节。
举个小例子来说明一下 到底什么是封装:
比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器,USB插孔等等,让用户来和计算机进行交互,完成日常事务;
但实际上,电脑正真工作的却是CPU、显卡、内存等一些硬性原件;
对于计算机使用者而言,不用关心 内部核心部件,比如主线板上线路是如何布局的,CPU内部是如何设计的等等,他们只需要知道,怎么去开关机、怎么通过键盘和鼠标 与计算机进行交互即可;
因此 计算机厂商在出厂时,在外部套上壳子,将内部实现细节隐藏起来,仅仅对外提供开关机、鼠标以及键盘、插孔等等,让用户可以与计算机进行交互即可。
那么,应该怎么样对 数据以及操作数据的方法 来进行封装呢?
这就涉及到了四个访问修饰限定符:public、private、protected、default 。
这个知识点博主把单独分享了出来,
大家感兴趣的话,可以点击下面的传送:
传送门正在建造中......
建造进度(100%)......
传送门:访问修饰限定符
首先创建对象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修饰的成员,称之为 静态成员(类成员),其不属于某一个具体的对象,而是所有的对象所共享的。
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); } }
静态成员变量 不建议 通过 对象名.静态成员变量 来进行访问(这样写是合法不合理的):
【静态成员变量的静态属性】
一般类中的数据成员 都设置为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(); } }
【静态方法特性】
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一个对象,这就解释了为什么一开始在写主函数的时候,是要这样写的:
【注意】静态成员变量 一般不会放在构造方法中来初始化,构造方法中初始化的是 与对象相关的实例属性;
静态成员变量的初始化分为两种:就地初始化 和 静态代码块初始化。
就地初始化 指的是:在定义时直接给出初始值:
class Student{
public String name;
public int age;
public double score;
public static String classes = "Java";
//......
}
在学习这一部分内容的时候,还是需要来介绍一下什么是代码块......
使用 {} 定义的一段代码称为代码块。
根据代码块定义的位置 以及关键字,又可分为以下四类:
普通代码块:定义在方法中的代码块:
构造代码块:定义在类中的代码块(不加修饰符),也叫:实例代码块。
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);
}
}
使用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);
}
}
内部类也是一种类,其重点在于内部二字;
在一个类的内部 定义的类,叫做 内部类。
内部类 可以分为以下几种:
所以说,以后 如果说内部类的时候,需要带上前缀(不同的内部类,性质、使用方式等等都是有区别的)。
class OuterClass {
//普通成员变量(实例成员变量)
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
class InnerClass {
//class InterClass 这个类就叫做 实例内部类
}
}
//外部类名.内部类名 变量 = 外部类对象的引用.new 内部类名();
原因:内部类InnerClass需要 外部类对象 才能够进行实例化的,如果里面有 静态static,那么data6就不需要外部类对象。
当然,也不可以含有静态方法,大家可以自己去试一试:
如果要定义,必须是 编译的时候就要确定的值(即:必须是 static finna的)(内部类里面内部类里面内部类里面):
如果实在内部类外面定义,那就肯定是编译错误:
那么,就会优先使用 内部类(自己)的:
那么,如何去调用 外部类的data1呢?
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);
}
}
被static修饰的内部类叫做 静态内部类。
class OuterClass2 {
public int data1 = 10;
private int data2 = 20;
public static int data3 = 30;
static class InnerClass {
//这个类就叫做静态内部类
}
}
//外部类名.静态内部类名 变量 = new 外部类名.静态内部类名
在静态内部类当中,只能访问外部类的静态的成员:
如果要访问外部类的非静态成员,那么高怎么去访问呢?
——去提供外部类对象:
去访问方法的时候也是一样的,这里就不演示了。
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();
}
}
这部分内容等到后面 接口 的内容再详细介绍嗷......
传送门正在建造中......
建造进度(0%)......
花费了好几天的时间总结了关于 类与对象 的知识 到此就结束了;
当然,还有一些不足的地方;
后期也要修修改改;
希望大家收获满满呀!!!!!!
如果铁铁们可以一键三连那就更棒了,特别特别感谢 ୧(๑•̀⌄•́๑)૭ 。