Java小试牛刀—内部类与代码块

目录

1、前言

2、代码块

2.1 代码块概念以及分类

2.2 普通代码块

2.3 构造代码块

2.4 静态代码块

2.5 代码执行顺序

2.5.1 注意事项

3、内部类

3.1 什么是内部类

3.2 内部类的分类

3.3 实例内部类

3.3.1 实例内部类解读

3.4 静态内部类

3.4.1 静态内部类解读 

3.4.2 静态内部类的好处

3.5 局部内部类


1、前言

本次blog我们来共同学习以下Java当中的内部类以及代码块的知识,为今后的链表做做准备!

2、代码块

2.1 代码块概念以及分类

使用{} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下四种:
1、普通代码块
2、构造代码块
3、静态代码块
4、同步代码块(本次不进行讲解)

2.2 普通代码块

普通代码块:定义在方法中的代码块,很少有人这么用它,因为逻辑比较奇怪。

public class Main{
    public static void main(String[] args) {
    { //直接使用{}定义,普通方法块
    int x = 15;
    System.out.println("x1 = " +x);
    }
    int x = 150 ;
    System.out.println("x2 = " +x);
    }
}
// 执行结果
x1 = 15
x2 = 150

2.3 构造代码块

  • 构造代码块,也叫实例代码块:定义在类中的代码块(不加修饰符),构造代码块一般用于初始化实例成员变量。
public class codeBlock {
    public String name;
    public double score;
    public int age;
    public static String classes = "520class";

    //实例化代码块
    {
        name = "wujianyong ";
        System.out.println("实例化代码块");

    }


    public static void main(String[] args) {
        codeBlock student1 = new codeBlock("meng",60.0,18);
        System.out.println("==============================");
        codeBlock student2 = new codeBlock("wujian",29.0,28);
    }
}

2.4 静态代码块

  • 使用static定义的代码块称为静态代码块,一般用于初始化静态成员变量
public class codeBlock {
    public String name;
    public double score;
    public int age;
    public static String classes = "520class";

    static{
        classes = "520";
        System.out.println("静态代码块");
    }


    public static void main(String[] args) {
        codeBlock student1 = new codeBlock("meng",60.0,18);
        System.out.println("==============================");
        codeBlock student2 = new codeBlock("wujian",29.0,28);
    }
}

2.5 代码执行顺序

1、当代码中有静态代码块、实例代码块、以及构造方法的时候,如果这是只创建了一个对象,那么执行顺序是:

静态代码块—>实例代码块—>构造方法

2、当代码中有静态代码块、实例代码块、以及构造方法的时候,此时创建了两个或多个对象,那么执行第二个及以后的对象的时候,就不会执行静态代码块了,静态代码块只会执行一次

student1执行:静态代码块—实例代码块—构造方法。

student2执行:实例化代码块—构造方法(不重复执行静态代码块

3、 如果有多个静态的代码块,那就看定于的顺序,按顺序执行。 下面代码先执行classes = 520。后面改成classes = 521。

public class codeBlock {
    public String name;
    public double score;
    public int age;
    public static String classes = "520";

    static{
        classes = "521";
        System.out.println("静态代码块");
    }
    static{
        classes = "521";
        System.out.println("静态代码块");
    }

   

    public static void main(String[] args) {
        codeBlock student1 = new codeBlock("meng",60.0,18);
        System.out.println("==============================");
        codeBlock student2 = new codeBlock("wujian",29.0,28);
    }
}

4、如果没有创建对象,也就是没有实例化对象,那么只会执行静态代码块不会执行实例化代码块和构造代码块。

2.5.1 注意事项

  • 静态代码块不管生成多少个对象,其只会执行一次;
  • 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的;
  • 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次合并;
  • 实例代码块只有在创建对象时才会执行。

3、内部类

3.1 什么是内部类

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

注意:

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

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

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

3.2 内部类的分类

public class OutClass {
// 成员位置定义:未被static修饰 --->实例内部类
    public class InnerClass1{
    }
    // 成员位置定义:被static修饰 ---> 静态内部类
    static class InnerClass2{
    }
    public void method(){
// 方法中也可以定义内部类 ---> 局部内部类:几乎不用
        class InnerClass5{
        }
    }
}

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

1、局部内部类:定义才方法内部的一种类,几乎不用(这里不过多介绍);

2、实例内部类:未static修饰的成员内部类;

3、静态内部类:被static修饰的成员内部类;

4、匿名内部类

3.3 实例内部类

  • 以下的实例内部类的讨论都是基于这个代码展开,其中OuterClass是外部类,InnerClass是实例内部类(没有static修饰)
class OuterClass{
    public int data1 = 1;
    private int data2 = 2;
    public static int data3 = 3;
    //外部类中的内部类
    class InnerClass{
        public int data1 = 11111;
        public int data4 = 4;
        private int data5 = 5;
        public static final int data3 = 6;


      /*  public static int a = 10;//定义静态的变量;
        public static final int data3 = 10;//加上final才能定义*/

       /* public static void innerFunction(){

        }*/

        public void innerFunction(){
            System.out.println(data1);//优先打印出内部类中的data1变量
            System.out.println(this.data1);//打印出内部类中的data1变量
            System.out.println("外部类的非静态的data1:"+OuterClass.this.data1);//打印出外部类中的data1变量
            System.out.println("外部类的静态的data3:"+OuterClass.data3);//打印出外部类中的data3变量
            System.out.println("外部类的private的data2:"+OuterClass.this.data2);//外部类中的private变量能访问到,因为都在外部类的{}中,内部类也在外部类的{}内部。
        }

    }

    //在内部类的外部,建立一个外部类的方法,想要调用内部类的成员变量,要先创建内部类的对象,才能访问内部类中的成员变量。
    public void func2(){
        InnerClass inner = new InnerClass();
        System.out.println(inner.data5);

    }
}

public class Test {

    public static void main(String[] args) {
        //第一种定义对象的方法
        /*OuterClass out = new OuterClass();//先建立一个外部类的对象
        OuterClass.InnerClass inner =out.new InnerClass();//以这种形式建立内部类的对象,就可以实例化了*/
        //第二种定义对象的方法
//        OuterClass.InnerClass inner = new OuterClass().new InnerClass();
//        System.out.println(inner.data1);
/*        inner.innerFunction();
        out.func2();*/

    }

}

3.3.1 实例内部类解读

1、因为实例内部类与外部的成员变量的位置相同,所以InnerClass可以加上public/private等,或者不加都可以。 

2、实例内部类中,不能定义静态的成员方法 

 3、在实例化内部类中,要定义静态的成员变量加final,不能直接定义静态的成员变量。

 4、

(1)要实例化内部类,就是可以访问内部实例类中成员变量或方法(变量名.成员变量或者变量名.成员方法),要依赖于外部类的对象,所以要先建立一个外部类对象。 

定义方式: 先建立一个外部类的对象(这里引用变量为out)

                   之后:外部类类名.内部类 变量名 = 外部类引用变量名.new 内部类名(),即可

    OuterClass out = new OuterClass();//先建立一个外部类的对象
    OuterClass.InnerClass inner =out.new InnerClass();//以这种形式建立内部类的对象,就可以实例化了

(2)也可以用以下的方法来实例化,相当于2步合成一步了,把创建Outer的对象的方法集成到一起了。inner是实例化内部类的变量名

//第二种定义对象的方法
OuterClass.InnerClass inner = new OuterClass().new InnerClass();

5、在外部类和内部类变量名相同的时候,优先访问内部类中的变量 

 6、如果外部类和内部类变量(非静态)同名的变量,想访问外部类OuterClass的data1的方法,通过外部类名.this.外部类的变量名。因为实例内部类中包含了外部类.this。

System.out.println(data1);//优先打印出内部类中的data1变量
System.out.println(this.data1);//打印出内部类中的data1变量
System.out.println("外部类的非静态的data1:"+OuterClass.this.data1);//打印出外部类中的data1变量

 7、如果外部类和内部类静态变量同名的变量,想访问外部的静态变量,还是用外部类名.静态变量名就好了,可以不加this(补一个不加this的图)

System.out.println("外部类的静态的data3:"+OuterClass.data3);//打印出外部类中的data3变量

8、想要访问外部类中的private变量,因为这个内部类InnerClass的代码也在外部OuterClass的{}中,所以private的变量一定能访问到。

System.out.println("外部类的private的data2:"+OuterClass.this.data2);//外部类中的private变量能访问到,因为都在外部类的{}中,内部类也在外部类的{}内部。

9、在外部类中创建一个外部类方法func2(不是在内部类中),在func2中想要访问内部类的成员,必须先在func2方法中创建内部类的对象。不需要再创建外部类对象了(OuterClass)

3.4 静态内部类

  • 静态内部类的讨论都是基于以下代码,其中 OuterClass是外部类,static修饰的的InnerClass是静态内部类
class OuterClass {
    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 OuterClass outer ;
        //用构造方法来建立对象,上面有public OuteClass outer这个对象。
        public InnerClass(OuterClass outer) {
            System.out.println("静态内部类的构造方法!");
            this.outer = outer;
        }*/

        public void test1(){

            System.out.println(OuterClass.data3);
//            System.out.println(OuterClass.this.data1);
//            System.out.println(outer.data2);
            System.out.println(data4);
            System.out.println(data5);
            System.out.println(InnerClass.data6);

        }


        //在函数内部建立OuterClass的对象
        public void test() {
            System.out.println("test方法执行了!");
            OuterClass outerClass = new OuterClass();
            System.out.println(outerClass.data1);

            System.out.println(outerClass.data2);
            System.out.println(OuterClass.data3);
            System.out.println(this.data4);
            System.out.println(this.data5);
            System.out.println(InnerClass.data6);
        }
        /*public static void test2() {
            System.out.println("test2");
        }*/
    }

}
public class Test {
    public static void main1(String[] args) {
        //第一种方法
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();//实例化静态内部类
        innerClass.test();

        //第二种方法传参
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
        innerClass.test1();

    }
}

3.4.1 静态内部类解读 

1、如何实例化静态内部类中的成员,用外部类名.内部类名 变量名 = new 外部类名.内部类名()即可,不需要创建外部类的对象

    public static void main1(String[] args) {
        //第一种方法
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();//实例化静态内部类
        innerClass.test();

        //第二种方法传参
        OuterClass outer = new OuterClass();
        OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
        innerClass.test1();

    }

2、

(1)静态内部类中只能访问外部类中的静态成员,用外部类名.变量名即可。

(2)如果非要访问外部类中的非静态成员,要在静态内部类中创建外部类的对象,或者传参,通过变量名.成员名来访问外部类中的非静态成员。

3、在静态内部类中,不能用外部类.this+变量名的形式访问外部类中的非静态成员 

4、在静态类内部,访问自己类中的成员,正常访问即可,静态的变量还是用类名.变量名,不用也可以访问到。 

3.4.2 静态内部类的好处

  • 实例化静态内部类对象不需要创建外部类的对象实例化实例内部类,必须先创建外部类的对象才可以。
OuterClass.InnerClass innerClass = new OuterClass.InnerClass();//实例化静态内部类
  •  注意:在静态内部类中只能直接访问外部类中的静态成员,想要访问外部类的非静态成员需要先建立外部类的对象。

3.5 局部内部类

  • 定义在外部类的方法体或者{}中,该种内部类只能在其定义的位置使用,一般使用的非常少。
    public class OutClass {
        int a = 10;
        public void method(){
            int b = 10;
// 局部内部类:定义在方法体内部
// 不能被public、static等访问限定符修饰
            class InnerClass{
                public void methodInnerClass(){
                    System.out.println(a);
                    System.out.println(b);
                }
            }
// 只能在该方法体内部使用,其他位置都不能用
            InnerClass innerClass = new InnerClass();
            innerClass.methodInnerClass();
        }
        public static void main(String[] args) {
// OutClass.InnerClass innerClass = null; 编译失败
        }
    }
  • 注意:

1. 局部内部类只能在定义的方法中使用;
2. 局部内部类不能被public、static等修饰符修饰;
3. 局部内部类编译器也有自己独立的字节码文件,命名格式:外部类名字$内部类名字.class。

猜你喜欢

转载自blog.csdn.net/weixin_44580000/article/details/124927236