面向对象编程(进阶)

一、类变量和类方法

1. 类变量的概述

        类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问

它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。

2. 类变量的定义

定义语法:

访问修饰符 static 数据类型 变量名;//推荐

static 访问修饰符 数据类型 变量名;

3. 类变量的访问

类名.类变量名; //推荐 ,静态变量访问修饰符访问权限访问范围普通属性一样

对象名.类变量名; 

4. 类变量使用注意事项

 ① 什么时候需要使用:

     当我们需要让某个类的所有对象共享一个变量时,就可以考虑使用类变量(静态变量)

     比如:定义学生类,统计所有学生共交多少钱。

                Student (name,static fee)

② 类变量与示例变量 (普通属性) 区别

    类变量是该类的所有对象共享的,而示例对象是每个对象独享

③ 加上 static 称为类变量或静态变量否则称为实例变量/普通变量/非静态变量

④ 类变量可以通过 类名.类变量名 或者 对象名.类变量名 来访问,但Java设计者推荐我们

     使用类名.类变量名方式访问。【前提是 满足访问修饰符的访问权限和访问范围】

实例变量不能通过 类名.类变量名 方式访问

⑥ 类变量是在类加载时就初始化了,也就是说,即使你没有创建对象,只要类加载了,

     就可以使用类变量了

⑦ 类变量的生命周期是随类的加载开始,随着类消亡而销毁

5. 类方法基本介绍

        类方法也叫静态方法

形式如下:

访问修饰符 static 数据返回类型 方法名(){} //推荐

static 访问修饰符 数据返回类型 方法名(){}

6. 类方法的调用

类名.类方法名        //前提是满足访问修饰符的访问权限和访问范围

对象名.类方法名 

7. 类方法使用场景

当方法中不涉及任何和对象相关的成员,则可以将方法设计成静态方法,提高开发效率 

        例如:工具类中的方法 utils

                   Math类、Arrays类、Collections集合类看下源码;

小结:

在程序员实际开发,往往会将一些通用的方法设计成静态方法,这样我们不需要创建对象就可以使用了,比如打印一维数组,冒泡排序,完成某个计算任务等

8. 类方法使用注意事项

① 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区:

    类方法中无 this 的参数

    普通方法中隐含着 this 的参数

② 类方法可以通过类名调用,也可以通过对象名调用

普通方法和对象有关,需要通过对象名调用

    例如:对象名.方法名(参数)不能通过类名调用(需要先创建对象再调用)

类方法中不允许使用和对象有关的关键字,比如 this 和 super 

    普通方法(成员方法)可以

⑤ 类方法(静态方法)中,只能访问静态变量 或静态方法

⑥ 普通成员方法,既可以访问非静态成员,也可以访问静态成员

小结:

        静态方法,只能访问静态的成员

        非静态的方法,可以访问静态成员和非静态成员

        (必须遵守访问权限) 

class Person { 
    private int id; 
    private static int total = 0; 

    public static void setTotalPerson(int total){
        // this.total = total;//错误,因为在 static 方法中,不可以使用 this 关键字 
    
        Person.total = total; 
    }

    public Person() {//构造器 
        total++; 
        id = total; 
    }
} 
public class TestPerson { 
    public static void main(String[] args) { 
        Person.setTotalPerson(3); 
        new Person(); //最后 total 的值就是 4 
    } 
}

二、理解 main 方法语法

1. 解释 main 法的形式

public static void main(String[] args){}

        ① main 方法时虚拟机调用

        ② Java 虚拟机需要调用类的 main() 方法,所有该方法的访问权限必须是 public

        ③ Java 虚拟机在执行 main()方法时不必创建对象,所有该方法必须是 static

        ④ 该方法接收 String 类型的数组参数,该数组中保存执行Java 命令时传递给所

            运行类的参数,接收参数

        ⑤ Java 执行的程序 参数1 参数2 参数3

  

2. 注意事项

        ① 在 main() 方法中,我们可以直接调用 main 方法所在类静态方法静态属性

        ② 但是,不能直接访问该类中的非静态成员,必须访问该类的一个实例对象后,

            才能通过这个对象去访问类中的非静态成员(必须创建对象后才能用)

三、代码块

1. 代码块的概念

        代码块又称初始化块,属于类中的成员(即是类中的一部分),类似于方法,将逻辑语句

封装在方法体中,通过{}包围起来

        但是和方法不同,没有方法名,没有返回,没有参数只有方法体,而且不用通过对象或类

显示调用,而是加载类时,或创建对象时隐式调用

2. 基本语法

        [修饰符]{

                代码

        };

注意:

        ① 修饰符 可选,要写的话,也只能写 static

        ② 代码块分为两类,使用 static 修饰的叫静态代码块,没有 static 修饰的,

            叫普通代码块/非静态代码块

        ③ 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)

        ④  ;可以写上,也可以省略

 3. 代码块的好处

        ① 相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作

        ② 场景:如果多个构造器中都有重复语句,可以抽取到初始化块中,提高代码的重用性

        ③ 代码块的调用优先于构造器

4. 代码块使用注意事项

(1) static 代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,

并且只会执行一次,如果是普通代码块,每创建一个对象,就执行

(2) 类什么时候被加载 (重点

        ① 创建对象时(new)

        ② 创建子类对象实例,父类也会被加载 (继承的本质先加载父类再加载子类)

        ③ 使用类的静态成员时(静态属性,静态方法)

(3) 普通的代码块,在创建对象实例时,会被隐式的调用

     被创建一次,就会调用一次

     如果只是使用类的静态成员时,普通代码块并不会执行

小结:

        ① static 代码块是类加载时,执行,只会执行一次

        ② 普通代码块是在创建对象时调用的,创建一次,调用一次

        ③ 类加载的3种情况,需要记住

(4) 创建一个对象时,在一个类调用顺序是:(重点

        ① 调用静态代码块和静态属性初始化

        (注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和

        多个静态变量初始化,则按定义顺序调用)

        ② 调用普通代码块和普通属性的初始化

        (注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和

        多个普通属性初始化,则按定义顺序调用)

        ③ 调用构造方法

(5) 构造器 的最前面其实隐含了 super() 和调用普通代码块,静态相关的代码块,属性初始化,

     在类加载时,就执行完毕,因此是优先于构造器和普通代码块执行的

class A{

        public A(){ //构造器

                // 这里有隐藏的执行要求

                // ① super();

                // ② 调用普通代码块的

                System.out.println("ok");

        }

(6) 创建一个子类对象时(继承关系),静态代码块,静态属性初始化,普通代码块,普通属性

     初始化,构造方法的顺序如下 :

        ① 父类的静态代码块和静态属性 (优先级一样,按定义顺序执行)

        ② 子类的静态代码块和静态属性 (优先级一样,按定义顺序执行)

       

        ③ 父类的普通代码块和普通属性 (优先级一样,按定义顺序执行)

        ④ 父类的构造方法

        ⑤ 子类的普通代码块和普通属性 (优先级一样,按定义顺序执行) 

        ⑥ 子类的构造方法

(7) 静态代码块只能直接调用静态成员(静态属性和静态方法),

     普通代码块可以调用任意成员

class Person { 
    public static int total;//静态变量
    static {//静态代码块 
        total = 100; 
        System.out.println("in static block!");//(1),静态代码只在类加载的时候执行一次
    } 
}
public class Test { 
    public static void main(String[] args) { 
        System.out.println("total = "+ Person.total); //100 
        System.out.println("total = "+ Person.total); //100 
    } 
}

四、单例设计模式

1. 设计模式的概念

    ① 静态方法属性的经典使用

    ② 设计模式是在大量的实践中总结和理论化之后优选代码结构、编程风格、以及解决        问题的思考方式

        设计模式就像是经典的棋谱,不同的棋局,我们用不同的棋谱,免去我们自己再思考          和摸索

2. 什么是单例模式

单例(单个的实例):

① 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存      在一个对象实例,并且该类只提供一个取得其对象实例的方法

② 单例模式有两种方式:懒汉式饿汉式

3. 单例模式的应用

构造器私有化 =》防止直接 new

类的内部创建对象(该对象是static)

③ 向外暴露一个静态的公共方法。getlnstance

package com.hhh.single_; 

public class SingleTon01 {
    public static void main(String[] args) { 
        // GirlFriend xh = new GirlFriend("小红"); 
        // GirlFriend xb = new GirlFriend("小白"); 

        //通过方法可以获取对象 
        GirlFriend instance = GirlFriend.getInstance(); 
        System.out.println(instance); 
        
        GirlFriend instance2 = GirlFriend.getInstance(); 
        System.out.println(instance2); 
        
        System.out.println(instance == instance2);//T                                         
        //System.out.println(GirlFriend.n1); //... 
    } 
}
//有一个类, GirlFriend 
//只能有一个女朋友 
class GirlFriend { 
    
    private String name;
    //public static int n1 = 100; 
    //为了能够在静态方法中,返回 gf 对象,需要将其修饰为 static 
    //對象,通常是重量級的對象, 餓漢式可能造成創建了對象,但是沒有使用. 
    private static GirlFriend gf = new GirlFriend("小红红");
 
    //如何保障我们只能创建一个 GirlFriend 对象 
    //步骤[单例模式-饿汉式] 
    //1. 将构造器私有化 
    //2. 在类的内部直接创建对象(该对象是 static) 
    //3. 提供一个公共的 static 方法,返回 gf 对象 
    private GirlFriend(String name) { 
        System.out.println("構造器被調用."); 
        this.name = name; 
    }
    public static GirlFriend getInstance() { 
        return gf; 
    }
    @Override 
    public String toString() { 
        return "GirlFriend{" + 
            "name='" + name + '\'' + 
            '}'; 
    }
}
package com.hhh.single_; 
/**
* 演示懶漢式的單例模式 
*/ 
public class SingleTon02 { 
    public static void main(String[] args) { 
        //new Cat("大黃"); 
        //System.out.println(Cat.n1); 
        Cat instance = Cat.getInstance(); 
        System.out.println(instance); 

        //再次調用 getInstance 
        Cat instance2 = Cat.getInstance(); 
        System.out.println(instance2); 
        
        System.out.println(instance == instance2);//T 
    } 
}

//希望在程序運行過程中,只能創建一個 Cat 對象 
//使用單例模式 
class Cat { 
    private String name; 
    public static int n1 = 999; 
    private static Cat cat ; 
    //默認是 null 
    
    //步驟 
    //1.仍然構造器私有化 
    //2.定義一個 static 靜態屬性對象 
    //3.提供一個 public 的 static 方法,可以返回一個 Cat 對象 
    //4.懶漢式,只有當用戶使用 getInstance 時,才返回 cat 對象, 
    //  後面再次調用時,會返回上次創建的 cat 對象 
    // 從而保證了單例 
    private Cat(String name) { 
        System.out.println("構造器調用..."); 
        this.name = name; 
}
    public static Cat getInstance() { 
        if(cat == null) {//如果還沒有創建 cat 對象 
            cat = new Cat("小可愛"); 
        }
        return cat; 
    }
    
    @Override 
    public String toString() { 
        return "Cat{" + 
        "name='" + name + '\'' + 
        '}'; 
    } 
}

 4. 饿汉式 和 懒汉式的区别

① 二者最主要的区别在于创建对象的时机不同:

     饿汉式是在类加载就创建了对象实例

     而懒汉式是在使用时才创建

② 饿汉式不存在线程安全问题,懒汉式存在线程安全问题

饿汉式存在浪费资源的可能,因为如果程序员一个对象实例都没有使用,那么饿汉式

创建的对象就浪费了

     懒汉式是使用时才创建,就不存在这个问题

④ 在我们 JavaSE 标准类中,java.lang.Runtime 就是经典的单例模式

五、final 关键字

     final 是最后的、最终的,可以修饰类、属性、方法和局部变量。

在以下情况下会用到:

① 当不希望被继承时,可以用 final 修饰

② 当不希望父类的某个方法被子类 覆盖/重写(overrider) 时,可以用 final 关键字修饰

        访问修饰符 final 返回类型 方法名

③ 当不希望类的某个属性的值被修改,可以用 final 修饰

④ 当不希望某个局部变量被修改,可以使用 final 修改

(2) final 使用注意事项

1) final 修饰的属性又叫常量,一般用 XX_XX_XX 来命名

2) final 修饰的属性在定义时,必须赋初值,并且以后不能再修改

    赋值可以在如下位置之一:

            ① 定义时:如 public final double TAX_RATE=0.08;

            ② 在构造器中

            ③ 在代码块中

3) 如果 final 修饰的属性是静态的,则初始化的位置只能是:

            ① 定义时

            ② 在静态代码块,不能在构造器中赋值

4) final 不能继承,但是可以实例化对象

5) 如果类不是 final 类,但是含有 final 方法,则该方法虽然不能重写,但是可以被继承

    一般来说,如果一个类已经是 final 类了,就没有必要再将方法修饰成 final 方法

6) final 不能修饰构造方法

7) final 和 static 往往搭配使用,效率更高,不会导致类加载,底层编译器做了优化处理

        class Demo{

                public static final int i = 16;

                static{

                        System.out.println("hahaha");

                }

        }

8) 包装类(Integer,Double,Float,Boolean等都是 final),String 也是 final 类

 六、抽象类 (abstract)

        当父类的某些方法需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,

(用 abstract 修饰),那么这个类就是抽象类。

        abstract class Animal{

                String name;

                int age;

                abstract public void cry();

        }

2. 抽象类的介绍

        ① 用 abstract 关键字来修饰一个类时,这个类就叫抽象类

                访问修饰符 abstract 类名{}

        ② 用 abstract 关键字来修饰一个方法时,这个方法就是抽象方法

                访问修饰符 abstract 返回类型 方法名(参数列表);//没有方法体

        ③ 抽象类的价值更多作用是在于设计,是设计者设计好后,让子类继承并实现抽象类()

        ④ 抽象类,在框架和设计模式使用较多

3. 注意事项

        ① 抽象类不能被实例化

        ② 抽象类不一定要包含 abstract 方法,也就说,抽象类可以没有 abstract 方法

        ③ 一旦类包含了 abstract 方法,则这个类必须声明为 abstract

        ④ abstract 只能修饰类和方法,不能修饰属性和其他的

        ⑤ 抽象类可以有任意成员(抽象类的本质还是类)

             比如:非抽象方法、构造器、静态属性等

        ⑥ 抽象方法不能有主体

        ⑦ 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法

             除非它自己也声明为 abstract 类

        ⑧ 抽象方法不能使用 private、final static 来修饰,因为这些字都是和重写相

             违背的。

4. 抽象类最佳实践--模板设计模式

        抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在

抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。

(2) 模板设计模式能解决的问题

        ① 当功能内部一部分实现是确定,一部分实现是不确定的,这时可以不确定的部分

             暴露出去,让子类去实现

        ② 编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给

             其子类实现,就是一种模板模式

 七、接口 (interface)

        接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,

在根据具体情况把这些方法写出来。

语法:

        interface 接口名{

                //属性

                //方法  ① 抽象方法 

                           ② 默认实现方法(需要使用default关键字修饰) JDK 8以后才能

                           ③ 静态方法 JDK 8以后才能

        }

        class 类名 implements 接口{

                自己属性;

                自己方法;

                必须实现的接口的抽象方法

        }

小结:接口是更加抽象的抽象的类,抽象类里的方法可以有方法体,接口里的所有方法

           都没有方法体//JDK7.0

           接口体现了程序设计的多态和高内聚低耦合的设计思想。 //注:JDK8.0 后接口类可以有

           静态方法,默认方法,也就是说接口中可以有方法的具体实现

2. 注意事项

        ① 接口不能被实例化

        ② 接口中所有的方法是 public 方法,接口中抽象方法,可以不用 abstract 修饰

                void aaa();

                实际上是 abstract void aa();

        ③ 一个普通类实现接口,就必须将该接口的所有方法都实现

        ④ 抽象类实现接口,可以不用实现接口的方法

        ⑤ 一个类同时可以实现多个接口

        ⑥ 接口中的属性,只能是 final 的,而且是 public static final 修饰符。

                比如:int a = 1;

                实际上是 public static final int a =1;//必须初始化

        ⑦ 接口中属性的访问形式:接口名.属性名

        ⑧ 接口不能继承其他的类,但是可以继承多个别的接口

                interface A extends B,C{}

        ⑨ 接口的修饰符,只能是 public 和默认,这点和类的修饰符是一样的。

3. 接口和继承的区别

(1) 解决的问题不同

        继承的价值主要在于:解决代码的复用性和可维护性

        接口的价值主要在于:设计,设计好各种规范(方法),让其它类去实现这些方法

(2) 接口比继承更加灵活

        继承是满足 is - a 的关系,而接口只需满足 like - a 的关系

(3) 接口在一定程度上实现代码解耦,(即:接口规范性+动态绑定机制)

4. 接口的多态特性

        ① 多态参数

        ② 多态数组

        ③ 接口存在多态传递现象

八、内部类(重点InnerClass

        如果定义类在局部位置(方法中/代码块):

                局部内部类

                ② 匿名内部类

        定义在成员位置:

                ① 成员内部类

                ② 静态内部类

1. 基本介绍

        一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类 (inner class),

嵌套其他的类的类称为外部类 (outer class)。是我们类的第五大成员

        五大成员分别为:属性、方法、构造器、代码块、内部类

        内部类的最大特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系

2. 基本语法

        class Outer{ //外部类

                class Inner{ //内部类

                }

        }

        class Other{ //外部其他类

        }

3. 内部类的分类    

        定义在外部类的局部位置 (方法中/代码块):

                局部内部类 (有类名)

                ② 匿名内部类 (没有类名)

        定义在外部类的成员位置

                ① 成员内部类 (没用static修饰)

                ② 静态内部类 (使用static修饰)

 4. 局部内部类的使用 (LocalInnterClass)

        局部内部类是定义在外部类的局部位置,比如方法中,并且有类名

package com.hhh.innerclass;
public class LocalInnerClass {
    public static void main(String[] args) {  
        Outer02 outer02 = new Outer02(); 
        outer02.m1(); 
        System.out.println("outer02 的 hashcode=" + outer02); 
    } 
}
class Outer02 {
    private int n1 = 100; 
    
    private void m2() { 
        System.out.println("Outer02 m2()"); 
    }//私有方法 
    
    public void m1() {//方法 
        final class Inner02 {
            private int n1 = 800; 
            public void f1() { 
                //Outer02.this 本质就是外部类的对象, 即哪个对象调用了 m1, 
                //Outer02.this 就是哪个对象                     
                System.out.println("n1=" + n1 + " 外部类的 n1=" + Outer02.this.n1);                     
                System.out.println("Outer02.this hashcode=" + Outer02.this); 
                m2(); 
            } 
        }
        Inner02 inner02 = new Inner02(); 
        inner02.f1(); 
    } 
}

        ① 可以直接访问外部类的所有成员,包含私有

        ② 不能添加访问修饰符,因为它的地位就是一个局部变量,局部变量是不能使用

            修饰符的,但是可以使用 final 修饰,因为局部变量也可以使用 final

        ③ 作用域:仅仅在定义它的方法代码块

        

        ④ 局部内部类---访问--->外部类的成员  [访问方式:直接访问]

        ⑤ 外部类---访问--->局部内部类的成员

             访问方式 :创建对象,再访问(注意:必须在作用域内)

        记住:

        (1) 局部内部类定义在方法中/代码块

        (2) 作用域在方法体或代码块中

        (3) 本质仍然是一个类

        ⑥ 外部其他类---不能访问--->局部内部类 (因为局部内部类地位是一个局部变量)

        ⑦ 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类

             的成员,则可以使用 (外部类名.this.成员) 去访问 

                System.out.println("外部类的n2=" + 外部类名.this.n2);

5. 匿名内部类的使用(重点 AnonymousInnterClass) 

        ① 本质是类

        ② 内部类

        ③ 该类没有名字

        ④ 同时还是一个对象

        匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名

(1) 基本语法:

        new 类或接口(参数列表){

                类体

        }; 

package com.hhh.innerclass;

public class AnonymousInnerClass { 
    public static void main(String[] args) { 
        Outer04 outer04 = new Outer04(); 
        outer04.method(); 
    } 
}
class Outer04 { //外部类 
    private int n1 = 10;//属性 
    public void method() {//方法 
        //基于接口的匿名内部类  
        
        // 要求Tiger/Dog 类只是使用一次,后面再不使用
        // tiger 的编译类型 IA 
        // tiger 的运行类型 , 就是匿名内部类 Outer04$1
            
        class Outer04$1 implements IA { 
            @Override 
            public void cry() { 
            System.out.println("老虎叫唤..."); 
        } 
    }  
    // jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例, 
    // 并且把地址返回给 tiger 
    // 匿名内部类使用一次,就不能再使用,但是tiger还可以继续调用 
    IA tiger = new IA() { 
        @Override 
        public void cry() { 
            System.out.println("老虎叫唤..."); 
        } 
    }; 
    System.out.println("tiger 的运行类型=" + tiger.getClass()); 
    tiger.cry(); 
    tiger.cry(); 
    tiger.cry(); 

    // IA tiger = new Tiger(); 
    // tiger.cry();
}

        (2) 匿名内部类既是一个类的定义,同时它本身也是一个对象,因此从语法上看,

             它既有定义类的特征,也有创建对象的特征,因此可以调用匿名内部类方法

        (3) 可以直接访问外部类的所有成员,包含私有的

        (4) 不能添加访问修饰符,因为它的地位就是一个局部变量

        (5) 作用域:仅仅在定义它的方法或代码块中

        (6) 匿名内部类---访问--->外部类成员 [访问方式:直接访问]

        (7) 外部其他类---不能访问--->匿名内部类(因为它的地位就是一个局部变量)

        (8) 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近

             原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员) 去访问

        匿名内部类最佳实践当作实参直接传递,简洁高效

package com.hhh.innerclass; 
import com.hhh.abstract_.AA; 

public class InnerClassExercise01 { 
    public static void main(String[] args) { 
        f1(new IL() { 
            @Override 
            public void show() { 
                System.out.println("这是一副名画~~..."); 
            } 
        }); 
        //传统方法 
        f1(new Picture()); 
    } 
    
    //静态方法,形参是接口类型 
    public static void f1(IL il) { 
        il.show(); 
    } 
}
//接口 
interface IL { 
    void show(); 
}
//类->实现 IL => 编程领域 (硬编码) 
class Picture implements IL { 
    @Override 
    public void show() { 
        System.out.println("这是一副名画 XX..."); 
    } 
}

6. 成员内部类的使用 (MemberInnterClass

        成员内部类是定义在外部类的成员位置,并且没有 static 修饰

        ① 可以直接访问外部类的所有成员,包含私有的

class Outer01{ //外部类

        private int n1 = 10;

        public String name = "张三";

        class Innter01{

                public void say(){

                System.out.println("Outer01 的 n1 =" + n1 + "Outer01 的 name = " + name);

                }

        }

}

        ② 可以添加任意访问修饰符(public、protected、默认、private),

            因为他的地位就是一个成员

        ③ 作用域:和外部类的其他成员一样,为整个类体

             比如:在外部类的成员方法中创建成员内部类对象,再调用方法

       

        ④ 成员内部类---访问--->外部类成员(如:属性) [访问方式:直接访问]

        ⑤ 外部类---访问--->成员内部类 [访问方式:创建对象,再访问]       

        ⑥ 外部其他类---访问--->成员内部类

                Outer.Inner inner = Outer.new Inner();

                // 相当于把new Inner当成是Outer的成员

                

                //第二种方式,可以在外部类中,编写一个可以返回Inner对象的方法

                Outer.Inner innerInstance = Outer.getInnerInstance();

                innerInstance.say();

        ⑦ 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,

             如果想访问外部类的成员,则可以使用 (外部类名.this.成员) 去访问

7. 静态内部类的使用 (StaticInnerClass)

        静态内部类是定义在外部类的成员位置,并且有 static 修饰

        ① 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问静态成员

        ② 可以添加任意访问修饰符(public、protected、默认、private),因为他的地位就是

             一个成员

        ③ 作用域:同其他的成员,为整个整体

                class Outer{

                        private int n1 = 10;

                        private static String name = "张三";

                        static class Inner{

                                public void say(){

                                        System.out.println(name);

                                        //不能直接访问外部类的非静态成员

                                        System.out.println(n1);

                                }

                        }

                        public void show(){

                                //外部类使用内部类

                                new Inner().say();

                        }

                }

        ④ 静态内部类---访问--->外部类(如:静态属性) [访问方式:直接访问所有静态成员]

       

        ⑤ 外部类---访问--->静态内部类 [访问方式:先创建对象,再访问]

        ⑥ 外部其他类---访问--->静态内部类

        ⑦ 如果外部类和静态内部类的成员重名时,静态内部类访问时,默认遵循就近原则

             如果想访问外部类的成员,则可以使用 (外部类名.this.成员) 去访问

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值