作者:敲代码の流川枫

博客主页:​​流川枫的博客​​

专栏:​​和我一起学java​​

语录:Stay hungry stay foolish

工欲善其事必先利其器,给大家介绍一款超牛的斩获大厂offer利器——牛客网

点击免费注册和我一起刷题吧

文章目录

​​1. static修饰成员变量​​

​​2. static修饰成员方法​​

​​3. static成员变量初始化​​

​​4. 内部类​​

​​实例内部类​​

​​静态内部类​​

​​局部内部类​​


 

1. static修饰成员变量

在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的,例如:当我们定义学生类时,要表示学生上课的教室,这个教室的属性并不需要每个学生对象中都存储一份,而是需要让所有的学生来共享,这时要定义一个所有对象共享的静态成员

static修饰的成员变量,称为静态成员变量,静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的

静态成员变量特性:

1. 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中

2. 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问

3. 类变量存储在方法区当中

4. 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)

public class Class {
private String name;
private String gender;
private int age;
private static String classRoom = "A123";

public static void main(String[] args) {
//静态成员变量可以直接通过类名访问
System.out.println(Class.classRoom);

Class c1 = new Class();
Class c2 = new Class();
Class c3 = new Class();
//也可以通过对象访问:但是classRoom是3个对象共享的
System.out.println(c1.classRoom);
System.out.println(c2.classRoom);
System.out.println(c3.classRoom);
}
}

JavaSE——static、内部类_jvm

 以调试方式运行上述代码,然后在监视窗口中可以看到,静态成员变量并没有存储到某个具体的对象中

2. static修饰成员方法

Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的

public class Class {
private String name;
private String gender;
private int age;
private static String classRoom = "A123";
public static void setClassRoom(String classRoom) {
Class.classRoom = classRoom;
}

public static String getClassRoom() {
return classRoom;
}
}

class TestClass{
public static void main(String[] args) {
System.out.println(Class.getClassRoom());
}

}

输出:A123 

静态方法特性:

1. 不属于某个具体的对象,是类方法

2. 可以通过对象调用,也可以通过类名.静态方法名(...)方式调用,更推荐使用后者

3. 不能在静态方法中访问任何非静态成员变量

JavaSE——static、内部类_java_02

编译失败:无法从静态上下文中引用非静态变量this

'Class.this' cannot be referenced from a static context

JavaSE——static、内部类_内部类_03

 编译失败:无法从静态上下文中引用非静态变量age

Non-static field 'age' cannot be referenced from a static context

4. 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用

JavaSE——static、内部类_jvm_04

 编译报错:无法从静态上下文中引用非静态方法doClass()

3. static成员变量初始化

注意:静态成员变量一般不会放在构造方法中来初始化,构造方法中初始化的是与对象相关的实例属性

静态成员变量的初始化分为两种:就地初始化和静态代码块初始化

1. 就地初始化就地初始化指的是:在定义时直接给出初始值

2. 静态代码块初始化

JavaSE——static、内部类_jvm_05

用{}定义的一段代码称为代码块

根据代码块定义的位置以及关键字,又可分为以下四种:

普通代码块:定义在方法中的代码块.

构造块也叫:实例代码块。构造代码块一般用于初始化实例成员变量。

静态块:使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。

同步代码块

class TestClass{
public TestClass() {
System.out.println("不带参数的构造方法");
}

public static String classes;
{

System.out.println("实例代码块");
}
static {
System.out.println("静态代码块");
}
public static void main(String[] args) {
TestClass testClass = new TestClass();
}

}

JavaSE——static、内部类_servlet_06

 先执行了静态代码块,静态代码块在类加载的时候就会被执行,和代码顺序无关

JavaSE——static、内部类_内部类_07

 当我们再执行一遍时,静态代码块不会再执行了,态代码块不管生成多少个对象,其只会执行一次

注意事项:

静态代码块不管生成多少个对象,其只会执行一次

静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的

如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)

实例代码块只有在创建对象时才会执行

4. 内部类

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。在 Java 中,可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。内部类也是封装的一种体现

public class OutClass{
class InnerClass{

}
}
//OutClass是外部类
//InnerClass是内部类

注意事项:

1. 定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类

public class A{

}
class B{

}
//A和B是两个独立的类,彼此之前没有关系

2. 内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件

public class Test {
public static void main(String[] args) {
System.out.println("hello");
}
class Test1{
public void test(){

}
}
}

JavaSE——static、内部类_jvm_08

根据内部类定义的位置不同,一般可以分为以下几种形式:

1. 成员内部类(普通内部类:未被static修饰的成员内部类静态内部类:被static修饰的成员内部类)

2. 局部内部类(不谈修饰符)、匿名内部类(学习接口时介绍)

public class OutClass{

//成员位置定义:未被static修饰--->实例内部类

public class InnerClass1{
}

//成员位置定义:被static修饰--->静态内部类

static class InnerClass2{
}
public void method(){

//方法中也可以定义内部类--->局部内部类:几乎不用

classInnerClass5{
}
}
}

注意:内部类其实日常开发中使用并不是非常多,大家在看一些库中的代码时候可能会遇到的比较多,日常开始中使用最多的是匿名内部类

实例内部类

即未被static修饰的成员内部类

看四个问题:

1. 如何获取实例内部类的对象?

OuterClass.InnerClass innerClass = outerClass.new InnerClass();
public class Test {
//1:如何获取实例内部类的对象
OuterClass outerClass = new OuterClass();
//通过外部类对象的引用来调用内部类,可以把实例内部类当作外部类的一个成员
OuterClass.InnerClass innerClass = outerClass.new InnerClass();

//两种写法都可
OuterClass.InnerClass innerClass2 = new OuterClass().new InnerClass();
}
class OuterClass{

public int data1;
int data2;
public static int data3;
public void test(){
System.out.println("OuterClass:test");
}
//实例内部类
class InnerClass{

public int data4;
int data5;
//public static int data6;
public void func(){
System.out.println("InnerClass:func");
}
}
}

2.  为何出错?

JavaSE——static、内部类_servlet_09

 实例内部类中不能有static的成员变量,必须要定义的话要用final修饰

static是定义类的成员,类加载的时候就已经会被执行,而内部类需要通过对象的引用才能执行,所以会出错

JavaSE——static、内部类_内部类_10

 final是常量,类似于C中的const,初始化之后是不能再修改的,编译之后已经定好了

3.外部类和内部类都有data1这个成员,调用时会打印哪个呢?

class OuterClass{

public int data1 = 1;
int data2 = 2;
public static int data3 = 3;
public void test(){
System.out.println("OuterClass:test");
}
//实例内部类
class InnerClass{

public int data1 = 4;
int data5 = 5;
public static final int data6 = 6;
public void func(){
System.out.println("InnerClass:func");

System.out.println(data1);
System.out.println(data2);
System.out.println(data3);
//System.out.println(data4);
System.out.println(data5);
System.out.println(data6);
}
}
}

JavaSE——static、内部类_外部类_11

访问的是内部类自己的成员

4.如果要在內部类中访问外部类中的相同的成员变量如何做?

JavaSE——static、内部类_外部类_12

 这样是可以的,或者 在实例内部类中使用外部类的引用:

JavaSE——static、内部类_内部类_13

 在实例内部类中使用外部类的引用写法:

System.out.println(OuterClass.this.data1);

注意事项:

1. 外部类中的任何成员都可以在实例内部类方法中直接访问

2. 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束

3. 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员来访问

4. 实例内部类对象必须在先有外部类对象前提下才能创建

5. 实例内部类的非静态方法中包含了一个指向外部类对象的引用

6. 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象

静态内部类

被static修饰的内部成员类称为静态内部类

看两个问题:

1.如何获取静态内部类对象?

OuterClass2.InnerClass2 innerClass2 = new OuterClass2.InnerClass2();
class OuterClass2{

public int data1 = 1;
int data2 = 2;
public static int data3 = 3;
public void test(){
System.out.println("OuterClass:test");
}
static class InnerClass2{

public int data1 = 4;
int data5 = 5;
public static int data6 = 6;
public void func(){
System.out.println("InnerClass2:func");
}
}

public static void main(String[] args) {
OuterClass2.InnerClass2 innerClass2 = new OuterClass2.InnerClass2();
}
}

2.  静态内部类当中不能访问外部类的非静态成员,外部类的非静态成员需要外部类的对象的引用才能访问

如果要访问:

JavaSE——static、内部类_servlet_14

 注意事项:

1. 在静态内部类中只能访问外部类中的静态成员

2. 创建静态内部类对象时,不需要先创建外部类对象

局部内部类

定义在外部类的方法体或者{}中,该种内部类只能在其定义的位置使用,一般使用的非常少,此处简单了解下语法格式

public class Test {
//局部内部类:定义在方法体内部
// 不能被public、static等访问限定符修饰
public void method(){
class InnerClass{

public void methodInnerClass(){
System.out.println("hello");
}

}
//只能在该方法体内部使用,其他位置都不能用
InnerClass innerClass= new InnerClass();
innerClass.methodInnerClass();
}

public static void main(String[] args) {
//编译失败
Test.InnerClassinnerClass=null;
}
}

注意事项:

1. 局部内部类只能在所定义的方法体内部使用

2. 不能被public、static等修饰符修饰

3. 编译器也有自己独立的字节码文件,命名格式:外部类名字$内部类名字.class

JavaSE——static、内部类_内部类_15

 一个类对应一个字节码文件

4. 几乎不会使用 

 “ 本期的分享就到这里了, 记得给博主一个三连哈,你的支持是我创作的最大动力!