深入理解类和对象(2) —— Java SE
目录
🐲 1. static 成员
🦄 1.1 static的作用
🦄 1.2 static修饰成员变量
🦄 1.3 static修饰成员方法
🐲 2.代码块
🦄2.1 普通代码块
🦄2.2 实例代码块(构造代码块)
🦄2.3 静态代码块
🐲 3. 理解内部类
🦄 3.1 内部类的分类
🦄 3.2 实例内部类
🦄 3.3 静态内部类
🦄 3.4 本地内部类
🐲 4.打印对象
🐲 1. static 成员
🦄 1.1 static的作用
先定义一个学生类
public class Student { public String name; public String gender; public int age; public double score; public Student(String name, String gender, int age, double score) { this.name = name; this.gender = gender; this.age = age; this.score = score; } public void PrintStudent(){ System.out.println(name + " " + gender + " " + age + " " + score); } public static void main(String[] args) { Student s1 = new Student("Zhang san","男",20,4.0); Student s2 = new Student("li si","男",21,3.9); Student s3 = new Student("Wing wu","男",22,2.9); s1.PrintStudent(); s2.PrintStudent(); s3.PrintStudent(); }}
🟦在Student类中定义的成员变量,每个对象中都会包含一份实例变量 ,也就是用来描述三个学生
🟪假如说这三个学生是一个班的,再来一个成员变量,用来表示这个班级,然后将这个成员变量对所有学生共享。
这就要用到,static来修饰成员变量了,
🟧被static修饰的成员叫静态成员,或者叫类成员,它对所有对象是共享的。
🦄 1.2 static修饰成员变量
🟥static 修饰的成员变量,叫做静态成员变量。
🟦作用是 这个静态成员变量是所有对象共享的,不是属于单独某个具体对象。
访问有两种方式
⚜️第一种 通过对象访问(不建议),
因为静态成员变量是所有对象共享的
⚜️第二种 直接通过类名来访问(建议使用这种)
好了,就是上面两种方法可以访问静态成员变量 ,
⚜️需要额外注意的两点是:
(1)类变量存储在方法区中
(2)生命周期同类一样
下面看一下全部代码
public class Student { //普通成员变量 public String name; public String gender; public int age; public double score; //静态成员变量,不属于对象 //被Static修饰就变成了静态成员,都可以使用这个,变成共享的 public static String classRoom = "gao yi 13 ban"; public Student(String name, String gender, int age, double score) { this.name = name; this.gender = gender; this.age = age; this.score = score; } public void PrintStudent(){ System.out.println(name + " " + gender + " " + age + " " + score); } public static void main1(String[] args) { //静态成员可以直接使用类名来访问 Student s1 = new Student("Zhang san","男",20,4.0); Student s2 = new Student("li si","男",21,3.9); Student s3 = new Student("Wing wu","男",22,2.9); //不建议通过对象的引用去访问 System.out.println(s1.classRoom); System.out.println(s2.classRoom); System.out.println(s3.classRoom); //建议最好通过类名去访问 System.out.println(Student.classRoom); //只是通过类名点出来的 s1.PrintStudent(); s2.PrintStudent(); s3.PrintStudent(); }}
🦄 1.3 static修饰成员方法
🟥static修饰成员方法,叫做静态成员方法,
🟦 静态成员方法是类的方法,不是某个对象所特有的,
静态成员一般是通过静态方法来访问
⚜️那么如何访问静态方法呢
因为静态方法是类方法,所以可以直接访问
class Student { public String name; public double score; public int age; public static String classRoom = "gao yi 13 ban" ; public Student(String name, double score, int age) { this.name = name; this.score = score; this.age = age; } public static void staticFunc(Student student) { System.out.println("这是一个静态的方法!也是类方法"); }}public class Test01 { public static void main(String[] args) { Student.staticFunc(); }}
⚜️先思考一下,如何在静态方法中,访问非静态的成员变量
首先,因为静态方法不需要对象,所以直接访问在静态方法访问非静态的成员变量,是不可行的。
其次,如果必须要访问,我们应该考虑的是,如何通过对象调用,使静态方法中,可以访问非静态的成员变量
有两种方法:
🟥第一种,既然要访问非静态成员变量,而静态方法又不需要对象,那么给静态方法中调用对象,不就可以了
🟪 第二种,也可以给静态方法个参数(建议使用这种)
⚜️再思考最后一个问题,静态方法中,可以调用非静态的方法吗?
🟪不可以直接调用,因为非静态方法有this参数,(this表示当前对象的引用)在静态方法中调用时候无法传递this引用
总结一下,
🟥静态方法是类方法,不属于某个具体的对象
🟧静态方法中,不能直接访问非静态的变量,
🟦静态方法中,也不能调用非静态的方法
🐲 2.代码块
使用{ }定义的一段代码叫代码块,根据代码块定义的位置和关键字,分为了4种
普通代码块,构造代码块,静态代码块,同步代码块,我们这里先讲解前3个代码块
🦄2.1 普通代码块
🟪定义在方法中的代码块,叫普通代码块
public static void main(String[] args) { { //1.普通代码块,直接用{}定义 int x = 10; System.out.println("x1="+x); } int x = 100; System.out.println("x2="+x); }
🦄2.2 实例代码块(构造代码块)
🟪定义在类中的代码块(前面没有修饰符)
🟦用于初始化实例成员变量
class Student{ private String name; private String gender; private int age; private double score; private static String classRoom; public Student(){ System.out.println("I am Student!"); } //实例代码块 { this.name = "zhang san"; this.age = 24; this.score = 45.6; System.out.println("I am Instance!"); } public void Show(){ System.out.println("name" + name + "age" + age + "score" + score); }}public class Test01 {public static void main(String[] args) { //2.构造代码块:定义在类中的代码块,也叫实例代码块 //一般用于初始化实例成员变量 Student student = new Student(); student.Show();}}
🦄2.3 静态代码块
🟪使用static定义的代码块
🟩用于初始化静态成员变量
class Student{ private String name; private String gender; private int age; private double score; private static String classRoom; static { classRoom = "gao er 13 ban "; System.out.println("I am static"); } public Student(){ System.out.println("I am Student!"); }}public class Test01 {public static void main(String[] args) { //3.静态代码块:用于初始化静态成员变量 Student s1 = new Student(); Student s2 = new Student();}}
注意:
🟥(1)静态代码块不管生成有多少个对象,只会执行一次
🟧(2)静态成员变量是类的属性,因此是在JVM加载类是开辟空间进行初始化
🟦(3)实例代码块只有在创建对象时才会执行
⚜️下面思考一个问题,
⚜️如果一个类中,有构造方法,实例代码块,静态代码块,执行的顺序是怎么样的
先执行静态代码块(如果有多个静态代码块,看定义顺序执行)(静态代码块只会执行一次),再执行实例代码块,最后执行构造方法
🐲 3. 理解内部类
如果内部类的完整结构只为外部事物提供服务,那么这个内部的完整结构最好使用内部类。
🟪将一个类定义在另一个类或者一个方法的内部,
🟥比如 InnerClass{}就是内部类,OuterClass{}就是外部类。
🟩内部类和外部类共用一个java源文件,经过编译后,内部类会形成单独的字节码文件
🦄 3.1 内部类的分类
在外部类中,内部类定义位置与外部类成员所处的位置相同,所以也叫做成员内部类
实例内部类 静态内部类 (本篇先介绍前两个)
本地内部类 匿名内部类
🦄 3.2 实例内部类
⚜️实例内部类就是没有static修饰的成员内部类
下面看这个例子 ,可以很清楚的看到实例内部类
class OuterClass{ public int date1 = 1; private int date2 = 2; public static int data3 = 3; //实例内部类,没有别static修饰 class InnerClass{ public int data4 = 4; private int data5 = 5; public static final int data3 = 6; public InnerClass(){ System.out.println("实例内部类的构造方法!"); } public void innerFunc(){ System.out.println("实例内部类的普通方法!"); System.out.println(date1); System.out.println(date2); System.out.println(data3); } }}public class Test01 { public static void main(String[] args) { OuterClass out = new OuterClass(); OuterClass.InnerClass innerClass = out.new InnerClass(); innerClass.innerFunc(); }}
通过上面代码,可以清楚知道
🟪在实例内部类中可以直接访问外部类中:任意访问限定符修饰的成员
⚜️ 1.下面思考一下,如果外部类和实例内部类具有相同名称的成员时,先访问谁,
并且如果要访问外部类同名成员时,如何访问?
那如果是同名的静态成员呢,如何访问?
🟦同名时,优先访问的是内部类自己的,
🟧要访问外部类同名成员时,按这样格式访问
外部类名称.this.同名成员名字
🟪外部类类名.同名成员名字
⚜️ 2.实例内部类中,不能直接定义静态的成员变量,如果必须要定义,如何做?
实例内部类中,可以定义静态方法吗?
🟪如果必须要定义,那么这个静态变量成员就应该被final所修饰
不可以,定义静态方法
⚜️ 3.如何实例化,实例内部类
有两种方法:
🟦外部类类名.内部类 变量=外部类引用,new 内部类();
🟩外部类类名.内部类 变量=new 外部类().new 内部类();
🦄 3.3 静态内部类
🟪被static修饰的内部成员类称为静态内部类。
下面看这个例子 ,可以很清楚的看到静态内部类
class OuterClass1{ public int data1 = 1; private int data2 = 2; public static int data3 = 3; static class InnerClass{ public int data4 =4; private int data5= 5; public static int data6 =6; public InnerClass(){ System.out.println("静态内部类的构造方法!"); } public void test(){ System.out.println("test方法执行了!"); System.out.println(data4); System.out.println(data3); System.out.println(data5); System.out.println(data6); } }}public class Test02 { public static void main(String[] args) { OuterClass1.InnerClass innerClass = new OuterClass1.InnerClass(); innerClass.test(); }}
通过上面代码,可以清楚知道
🟧 1. 在静态内部类中只能访问外部类中的静态成员 🟪 2. 创建静态内部类对象时,不需要先创建外部类对象
⚜️ 1.下面思考一下,如何拿到静态内部类中的对象
🟩外部类类名.内部类类名 变量 = new 外部类类名.内部类类名。
⚜️ 2.不能在静态内部类当中,直接访问外部类非静态的数据成员,那么怎么样才能访问到外部类非静态的数据成员?
有两种方法,都是靠对象来引用的
🟪第一种直接在内部类当中引用对象
🟧 第二种 通过参数引用
🦄 3.4 本地内部类
定义在外部类的方法体或者{}中,本地内部类只能在其定义的位置使用,这里简单了解一下
public class Test03 { public static void func() { class A{ public void test(){ System.out.println(100); } } A a = new A(); a.test(); } public static void main(String[] args) { func(); }}
🟧只能在该方法体内部使用,其他位置都不能用
🐲 4.打印对象
public class Test03 {class Person{ public String name; public int age; @Override//注解:注释【代表这个方法是重写父类的】+解释 public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}public class Test03{ public static void main(String[] args) { Person person = new Person(); System.out.println(person); }}
以后重写toSring可以借助IDea功能来快速写出