• 【迷人的爪哇】——Java的static成员、代码块、内部类


    目录

    一、static成员

    1.1 static修饰的成员变量

    1.2 static修饰成员方法

    二、代码块

    2.1 概念

    2.2 普通代码块(本地代码块)

    2.3 构造块(实例代码块)

    2.4 静态块

    三、内部类

    3.1 实例内部类

    3.2 静态内部类

    3.3 局部内部类

    3.4 匿名内部类

     四、对象的打印


    一、static成员

    1.1 static修饰的成员变量

    当我们定义一个类时,如果其中的某个成员变量不需要改变,我们可以用static来修饰它,称为静态成员变量,静态成员变量最大的特性是:不需要某个具体的对象,是所有对象所共享的。

    例如:

    1. class Student{
    2. public String name;
    3. public int age;
    4. public static String classRoom = "计科211";
    5. public Student(String name, int age) {
    6. this.name = name;
    7. this.age = age;
    8. }
    9. }
    10. public class Test {
    11. public static void main(String[] args) {
    12. Student student1 = new Student("zhangsan",10);
    13. Student student2 = new Student("lisi",15);
    14. System.out.println(Student.classRoom);
    15. System.out.println(Student.classRoom);
    16. }
    17. }

     我们也可以画图理解:

     静态成员变量特性:

    1. 不属于某个具体的对象,是类的属性,所有对象共享。
    2. 可以通过对象访问,也可以通过类名访问,但最好是类名访问。
    3. 它的生命周期伴随类的一生。
    4. final定义的常量不能修改,final定义的静态常量不能修改且必须初始化。

    1.2 static修饰成员方法

    当static修饰成员方法时,就称为静态方法,也叫类方法。

    例:

    1. class Student{
    2. public String name;
    3. public int age;
    4. public static String classRoom = "计科211";
    5. public Student(String name, int age) {
    6. this.name = name;
    7. this.age = age;
    8. }
    9. public static void Func(){
    10. System.out.println("静态方法");
    11. }
    12. }
    13. public class Test {
    14. public static void main(String[] args) {
    15. Student.Func();
    16. }
    17. }

     注:

    1. 静态方法的调用不需要引用对象,直接使用类名调用,因此静态方法内不能直接访问非静态的变量或方法。
    2. 在静态方法中可以创建对象来间接访问非静态数据。

    二、代码块

    2.1 概念

    使用 {} 定义的一段代码叫做代码块,可以分为一下几种:

    • 普通代码块(本地代码块
    • 构造块(实例代码块
    • 静态块
    • 同步代码块

    2.2 普通代码块(本地代码块

    定义在方法内部的代码块,一般很少用到:

    1. public static void Func(){
    2. System.out.println("静态方法");
    3. {
    4. System.out.println("本地代码块");
    5. }
    6. }

    2.3 构造块(实例代码块

    定义在类的内部,方法的外部。用来初始化实例成员变量,只有在创建对象时才会调用。

    1. class Student{
    2. public String name;
    3. public int age;
    4. public static String classRoom = "计科211";
    5. {
    6. this.name = "hh";
    7. this.age = 10;
    8. }
    9. }
    10. public class Test {
    11. public static void main(String[] args) {
    12. }
    13. }

    2.4 静态块

    static修饰的代码块,一般用来初始化静态成员变量。

    1. class Student{
    2. public String name;
    3. public int age;
    4. public static String classRoom;
    5. static{
    6. classRoom = "计科211";
    7. }
    8. }
    9. public class Test {
    10. public static void main(String[] args) {
    11. Student.Func();
    12. }

    当实例代码块、静态代码块、和构造方法同时出现时:

    其先执行静态代码块,然后执行实例代码块,最后执行构造方法。

    1. class Student{
    2. public String name;
    3. public int age;
    4. public static String classRoom = "计科211";
    5. public Student(String name, int age) {
    6. this.name = name;
    7. this.age = age;
    8. System.out.println("带有两个参数的构造方法");
    9. }
    10. public static void Func(){
    11. System.out.println("静态方法!");
    12. }
    13. {
    14. this.name = "haha";
    15. System.out.println("实例代码块!");
    16. }
    17. static{
    18. classRoom = "计科212";
    19. System.out.println("静态代码块!");
    20. }
    21. }
    22. public class Test {
    23. public static void main(String[] args) {
    24. Student student = new Student("hehe",10);
    25. }
    26. }

     当有两个静态方法时:

    1. class Student{
    2. public String name;
    3. public int age;
    4. public static String classRoom = "计科211";
    5. public Student(String name, int age) {
    6. this.name = name;
    7. this.age = age;
    8. System.out.println("带有两个参数的构造方法");
    9. }
    10. public static void Func(){
    11. System.out.println("静态方法!");
    12. }
    13. {
    14. this.name = "haha";
    15. System.out.println("实例代码块!");
    16. }
    17. static{
    18. classRoom = "计科212";
    19. System.out.println("静态代码块!");
    20. }
    21. }
    22. public class Test {
    23. public static void main(String[] args) {
    24. System.out.println(Student.classRoom);
    25. }
    26. }

    总结:

    1.  先执行静态的(加载了类就会被执行),且静态块只会执行一次。
    2. 如果有多个静态的,那么看定义顺序。
    3. 如果没有实例化对象,那么就只会执行静态的。
    4. 再执行实例化块,有多个实例化数据时就要看定义的顺序。
    5. 再执行构造方法。

    三、内部类

    1. 一个类定义在另一个类或者方法的内部,前者称为内部类,后者称为外部类。
    2. 内部类也是封装的一种体现。
    3. 一个文件里面的不是内部类,只有一个类中的才是。
    1. class OuterClass{
    2. class InnerClass{
    3. }
    4. }
    5. public class Test {
    6. }

    3.1 实例内部类

    1. class OuterClass{
    2. public int data1 = 1;
    3. private int data2 = 2;
    4. public static int data3 = 3;
    5. class InnerClass{
    6. public int data4 = 4;
    7. private int data5 = 5;
    8. public int data1 = 111;
    9. public InnerClass() {
    10. System.out.println("实例内部类的构造方法!");
    11. }
    12. public void innerFunc(){
    13. System.out.println("实例内部类的普通方法!");
    14. System.out.println(data1);
    15. //访问与内部类同名的外部类的成员变量
    16. System.out.println("外部类:"+ OuterClass.this.data1);
    17. System.out.println(data2);
    18. System.out.println(data3);
    19. System.out.println(data4);
    20. System.out.println(data5);
    21. }
    22. }
    23. }
    24. public class Test {
    25. public static void main(String[] args) {
    26. //OuterClass outerClass = new OuterClass();
    27. //OuterClass.InnerClass innerClass = outerClass.new InnerClass();
    28. //实例化内部类
    29. OuterClass.InnerClass innerClass = new OuterClass().new InnerClass();
    30. innerClass.innerFunc();
    31. }
    32. }

     总结:

    1. 实例内部类不能定义静态的成员变量,如果要定义,就要加final修饰。
    2. 实例内部类中不能定义静态的成员方法。
    3. 如果在实例内部类内访问同名的外部类由static修饰的成员变量时,直接外部类类名.成员变量。
    4. 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束。
    5. 会生成字节码文件: 外部类$内部类。

    3.2 静态内部类

    1. class OuterClass{
    2. public int data1 = 1;
    3. private int data2 = 2;
    4. public static int data3 = 3;
    5. static class InnerClass{
    6. public int data4 = 4;
    7. private int data5 = 5;
    8. public static int data6 = 6;
    9. private OuterClass outerClass;
    10. public InnerClass(OuterClass outerClass){
    11. System.out.println("静态内部类的构造方法!");
    12. this.outerClass = outerClass;
    13. }
    14. public void func(){
    15. System.out.println("func方法执行了!");
    16. //访问非静态外部类成员变量
    17. System.out.println(outerClass.data1);
    18. System.out.println(outerClass.data2);
    19. System.out.println(data3);
    20. System.out.println(data4);
    21. System.out.println(data5);
    22. System.out.println(data6);
    23. }
    24. }
    25. }
    26. public class Test2 {
    27. public static void main(String[] args) {
    28. //实例化静态内部类
    29. OuterClass.InnerClass innerClass = new OuterClass.InnerClass(new OuterClass());
    30. innerClass.func();
    31. }
    32. }

     注:

    1. 在静态内部类中只能访问外部类中的静态成员,不能在静态内部类中直接访问外部类的非静态的数据成员,可以通过实例化外部类对象来间接访问。
    2. 创建静态内部类对象时,不需要先创建外部类对象。

    3.3 局部内部类

    1. 局部内部类定义在方法体内部,之饿呢过在该方法体内使用,其他位置不能使用。
    2. 不能被public、static等访问限定符修饰。
    3. 也有独立的字节码文件,命名格式:外部类名字$内部类名字。
    1. public class Test2 {
    2. public static void fun(){
    3. class A{
    4. public void test(){
    5. System.out.println(1);
    6. }
    7. }
    8. A a = new A();
    9. a.test();
    10. }
    11. public static void main(String[] args) {
    12. fun();
    13. }
    14. }

    3.4 匿名内部类

    1. class Person{
    2. public String name;
    3. public int age;
    4. public void test(){
    5. System.out.println("lisi");
    6. }
    7. }
    8. public class Test2 {
    9. public static void main(String[] args) {
    10. //匿名对象,只能使用一次
    11. new Person().test();
    12. new Person(){
    13. @Override
    14. public void test() {
    15. System.out.println("77777");
    16. }
    17. }.test();
    18. }
    19. }

     

     四、对象的打印

    1. class Person{
    2. public String name;
    3. public int age;
    4. public Person(String name, int age) {
    5. this.name = name;
    6. this.age = age;
    7. }
    8. @Override
    9. public String toString() {
    10. return "Person{" +
    11. "name='" + name + '\'' +
    12. ", age=" + age +
    13. '}';
    14. }
    15. }
    16. public class Test3 {
    17. public static void main(String[] args) {
    18. Person person = new Person("zhangsan",10);
    19. System.out.println(person);
    20. }
    21. }

    当我重写ToString函数之后,编译器就会调用我重写的函数,可以实现对对象的打印,

  • 相关阅读:
    MOEAD原理及Python实现、MOEAD实现、基于分解的多目标进化、 切比雪夫方法-(python完整代码)
    递推递归与排列组合
    java多线程基础(上)
    如何用Python搭建监控平台
    5分钟,带你看完24岁60W年薪架构师的简历,上面竟然写着精通JVM
    多个列表参数一一对应使用枚举
    UNet语义分割网络
    sql登录报错18456和233怎么解决
    聚苯乙烯-SiO2/NiFe2O4磁性微球/中空介孔载银二氧化硅聚苯乙烯微球制备过程
    linux部署docker【centos】
  • 原文地址:https://blog.csdn.net/weixin_62678196/article/details/124928309