文章目录

  • 1.概述
  • 2.分类
  • 3.静态内部类
  • 4.成员内部类
  • 5.局部内部类
  • 6.匿名内部类(最常用)

1.概述

当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内 部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构最好使 用内部类

在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者 称为外部类。

Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完 整的名称。

内部类最大的优点,可以使用外部类私有化数据

2.分类

1.静态内部类

使用static修饰的内部类,相当于静态变量

2.成员内部类

没有static修饰的位于类体的内部类,相当于成员变量

3.局部内部类

方法中声明的内部类

4.匿名内部类(最常用)

3.静态内部类

public class OutterClass{
    static class InnerClass{
        public static void m1(){
            
        }
        public void m2(){
            
        }
    }
    public static void main(String[] args){
        //当前类中类名可以省略
        OuterClass.InnerClass.m1();
        InnerClass.m1();
        
        InnerClass ic = new OuterClass.InnerClass();
        InnerClass ic1 = new InnerClass();
        ic.m2();//成员属性必须创建对象才能使用
    }
}

注意:

可以使用权限修饰符: private protected public默认

先编译外部类,再编译内部类

类名为:外部类java 包中所有类 java类包含_内部类InnerClass

静态内部类中可以有任何申明(静态和成员都可以)

静态内部类中不能直接访问成员属性(需要有对象)

4.成员内部类

public class OuterClass{
    private static String s1 = "A";
    private String s2 = "B";
    class InnerClass{
        public void m2(){
            public void m2(){
                System.out.println(s1);
                System.out.println(s2);
            }
        }
    }
    public static void main(String[] args){
        //外部类
        OuterClass oc = new OuterClass();
        //创建内部类对象 外部类对象.new内部类();
        InnerClass ic = oc.new InnerClass();
        ic.m2();
    }
}

注意:

可以使用权限修饰符: private protected public默认

先编译外部类,再编译内部类

类名为:外部类java 包中所有类 java类包含_内部类InnerClass

成员内部类不能有静态申明

成员内部类可以访问外部类所有的数据

5.局部内部类

public class OuterClass{
    privaet static String s1 = "A";
    private String s2 = "B";
    public void m1(){
        // 1.8开始 可以不加final修饰,但是值还是不能更改的
		 int i = 10;
		class InnerClass{
			// 不能有静态声明
			// public static void m3(){}
			public void m4(){
				System.out.println(s1);
				System.out.println(s2);
				System.out.println(i);
			}
		}
		// 局部内部类的使用,必须在该方法中,因为作用域只在该方法中有效
		InnerClass in = new InnerClass();
		in.m4();
    }
    public static void m2(){

		// 1.8开始 可以不加final修饰,但是值还是不能更改的
		 int i = 10;
		class InnerClass{
			// 不能有静态声明
			// public static void m3(){}
			public void m4(){
				System.out.println(s1);
				// 需要对象调用
				// System.out.println(s2);
				System.out.println(new _03_OuterClass().s2);
				System.out.println(i);
			}
		}
		// 局部内部类的使用,必须在该方法中,因为作用域只在该方法中有效
		InnerClass in = new InnerClass();
		in.m4();
	
	}
	public static void main(String[] args) {
		_03_OuterClass oc = new _03_OuterClass();
		oc.m1();

		m2();
	}
}

注意:

局部内部类,访问外部方法的局部变量的时候,该局部变量必须使用final修饰
但是 1.8开始 final 可以省略,但是值依然不能更改

不管是成员方法还是静态方法,都不能使用static修饰局部内部类

不管是成员方法还是静态方法,局部内部类中都不可以声明静态属性

如果是成员方法的局部内部类,则可以直接访问外部类中的所有属性

如果是静态方法的局部内部类,则不能直接访问成员属性,需要有对象

类名 :
如果多个方法的内部类类名不一致,就是 : 外部类$1内部类
如果多个方法的内部类类名一致,就是 : 外部类$1内部类 , 外部类$2内部类 以此类推

6.匿名内部类(最常用)

public class _04_OuterClass {
	public static void main(String[] args) {
		String[] strs = { "123", "22", "321", "14" };
		// 默认排序 会按照ASCII码值进行比较
		// 但是如果我们想按照数值大小排序,就需要自定义规则
		// Arrays.sort(strs);
		// A a = new A();
		// 有一个传入Comparator比较器接口的方法
		// 因为接口不能创建对象,所有需要传入接口类型数据的地方,都需要我们传入该接口对应的实现类对象
		// 若此时这个实现类不经常使用,或者不被其他地方使用,则可以使用匿名内部类
		// Arrays.sort(strs, a);
		Arrays.sort(strs, new Comparator() {
			@Override
			public int compare(Object o1, Object o2) {
				System.out.println(this);
				String s1 = (String) o1;
				String s2 = (String) o2;
				return Integer.parseInt(s1) - Integer.parseInt(s2);
			}
		});
		for (String string : strs) {
			System.out.println(string);
		}
		
		m1(new C());
		m1(new B());
		m1(new B(){
			
		});
	}
	
	public static void m1(B b){
		
	}
}
class B{
	
}
class C extends B{
	
}
// class A implements Comparator{
// @Override
// public int compare(Object o1, Object o2) {
// String s1 = (String) o1;
// String s2 = (String) o2;
// return Integer.parseInt(s1) - Integer.parseInt(s2);
// }
// }

注意:

匿名内部类 : 是指在调用方法的时候,需要传入一个对象(一般是接口的实现类对象),

这个时候就可以不传递对象,传递一个匿名内部类

普通类也可以,一般是接口,匿名内部类 就等于是子类

语法 : 方法名(new 接口名(){ 实现类类体; });

传入匿名内部类的时候,会自动创建一个对象传入,因为没有名字,所以不能复用,我们也不能手动创建对象

类名为 外部类类名$1 , 一次类推

匿名内部类中 不能有静态声明 但是可以有常量(public static final)

入一个对象(一般是接口的实现类对象),

这个时候就可以不传递对象,传递一个匿名内部类

普通类也可以,一般是接口,匿名内部类 就等于是子类

语法 : 方法名(new 接口名(){ 实现类类体; });

传入匿名内部类的时候,会自动创建一个对象传入,因为没有名字,所以不能复用,我们也不能手动创建对象

类名为 外部类类名$1 , 一次类推

匿名内部类中 不能有静态声明 但是可以有常量(public static final)

不能直接访问外部类的成员属性,需要有对象