JavaSE——static、内部类

ced485cbb11e458d81a746890b32cf3f.gif

作者:敲代码の流川枫

博客主页:流川枫的博客

专栏:和我一起学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);
    }
}

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

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. 不能在静态方法中访问任何非静态成员变量

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

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

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

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

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

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

3. static成员变量初始化

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

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

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

2. 静态代码块初始化

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

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

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

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

静态块:使用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();
    }

}

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

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

注意事项:

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

静态成员变量是类的属性,因此是在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(){

        }
    }
}

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

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.  为何出错?

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

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

 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);
        }
    }
}

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

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

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

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

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.  静态内部类当中不能访问外部类的非静态成员,外部类的非静态成员需要外部类的对象的引用才能访问

如果要访问:

 注意事项:

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

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

4. 几乎不会使用 

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

ced485cbb11e458d81a746890b32cf3f.gif

猜你喜欢

转载自blog.csdn.net/chenchenchencl/article/details/126179618