锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 软件开发
  3. JavaSE——static、内部类

JavaSE——static、内部类

0
  • 软件开发
  • 发布于 2024-09-19
  • 0 次阅读
黄健
黄健

作者:敲代码の流川枫

博客主页:流川枫的博客

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

    }

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

  1. 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()

  1. 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加载类时开辟空间并初始化的

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

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

  1. 内部类

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使用内部类。在 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();
    }
}
  1. 静态内部类当中不能访问外部类的非静态成员,外部类的非静态成员需要外部类的对象的引用才能访问

如果要访问:

注意事项:

  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

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

  1. 几乎不会使用
    ” 本期的分享就到这里了, 记得给博主一个三连哈,你的支持是我创作的最大动力!

原文链接: https://blog.csdn.net/chenchenchencl/article/details/126179618

标签: #JAVA 991 #软件开发 1171
相关文章

万字:支付“核心系统”详解 2024-11-02 15:33

专栏作者:隐墨星辰 \| 主编:陈天宇宙 这篇文章也尝试化繁为简,探寻支付系统的本质,讲清楚在线支付系统最核心的一些概念和设计理念。 虽然支付行业已经过了风头最劲的时光,但跨境支付仍然在蓬勃发展,每年依然有很多新人进入这个行业,这篇文章尝试为这些刚入行的新人提供一点帮助。 文章只介绍一些支付行业十几

资深支付架构师视角:实战从问题定义到代码落地的完整套路 2024-11-02 15:33

前言 今天从一个实际案例入手,介绍站在架构师的角度,如何识别并定义问题,提炼需求,技术方案选型,再到详细设计,最后利用AI的能力协助写出核心的代码,验证与调优。 解决问题存在一定的模式,也可以称之为框架,总结出自己的思考和解题框架,以后再碰到同类型的问题就可以如庖丁解牛一样容易。 很多年前,我写代码

Spring 实现 3 种异步接口 2024-10-18 09:07

大家好,我是苏三~ 如何处理比较耗时的接口? 这题我熟,直接上异步接口,使用 Callable、WebAsyncTask 和 DeferredResult、CompletableFuture等均可实现。 但这些方法有局限性,处理结果仅返回单个值。在某些场景下,如果需要接口异步处理的同时,还持续不断地

重学SpringBoot3-集成Redis(五)之布隆过滤器 2024-10-08 11:24

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》 期待您的点赞👍收藏⭐评论✍ 重学SpringBoot3-集成Redis(五)之布隆过滤器 1. 什么是布隆过滤器? * 基本概念 适用场景 2. 使用 Redis 实现布隆过滤器 * 项目依赖 Redis 配置

设计模式第16讲——迭代器模式(Iterator) 2024-10-08 11:24

一、什么是迭代器模式 迭代器模式是一种行为型设计模式,它提供了一种统一的方式来访问集合对象中的元素,而不是暴露集合内部的表示方式。简单地说,就是将遍历集合的责任封装到一个单独的对象中,我们可以按照特定的方式访问集合中的元素。 二、角色组成 抽象迭代器(Iterator):定义了遍历聚合对象所需的方法

vue2路由和vue3路由区别及原理 2024-10-08 11:24

一、Vue2 与 Vue3 路由的区别 1. 创建路由实例方式的不同 Vue 2 中,通过 Vue.use() 注册路由插件,并通过 new VueRouter() 来创建路由实例。 import Vue from 'vue';import VueRouter from 'vue-router';i

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.