Java内部类详解(二)

三、种类

局部内部类、成员内部类、匿名内部类、静态内部类。

1. 局部内部类

局部内部类:是指内部类定义在方法或代码块内的类。

1.1 与局部变量一样,不能用public, protected, private和static修饰。

1.2 只能访问外部类的方法或代码块中定义为final类型的局部变量。

1.3 只能在方法或代码块中使用,即只能在方法或代码块当中生成局部内部类的实例并且调用其方法,并不对外界透明。

例子:

package com.learnjava.innerclass;

class LocalInner
{
    int a = 1;

    public void doSomething()
    {
        int b = 2;
        final int c = 3;
        // 定义一个局部内部类
        class Inner3
        {
            public void test()
            {
                System.out.println("Hello World");
                System.out.println(a);

                // 不可以访问非final的局部变量
                // error: Cannot refer to a non-final variable b inside an inner
                // class defined in a different method
                // System.out.println(b);

                // 可以访问final变量
                System.out.println(c);
            }
        }

        // 创建局部内部类的实例并调用方法
        new Inner3().test();
    }
}

public class LocalInnerClassTest
{
    public static void main(String[] args)
    {
        // 创建外部类对象
        LocalInner inner = new LocalInner();
        // 调用外部类的方法
        inner.doSomething();
    }
}

2. 成员内部类

成员内部类:定义在外部类方法之外的类,即外部类的成员。

2.1 可以直接使用外部类的所有成员和方法,不论是静态的,还是非静态的,即使是private的也可以访问。

可直接使用Outer.this表示外部类对象。

2.2 外部类要访问内部类的所有成员变量/方法,则需要通过内部类的对象来获取,而不能通过inner.this。例如:

public class Outer {

//	private Inner inner = new Inner();
//	private String a = inner.b;
//	private String a = inner.getB();

	private String a = new Inner().b;
	
	private class Inner {
		
		private String b = "11";
		
		public String getB() {
			return b + "22";
		}
	}
	
	public String getA() {
		return a;
	}
	
	public static void main(String[] args) {
		Outer outer = new Outer();
		System.out.println(outer.getA());
	}
}

2.3 其他类要直接创建内部类,必须首先创建外部类,且受访问级别的限制。

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

2.4 成员内部类不能含有static的变量和方法(除非定义为static final)。因为成员内部类需要先创建了外部类,才能创建它自己的,了解这一点,就可以明白更多事情,在此省略更多的细节了。

例子:

package com.learnjava.innerclass;

class MemberInner
{
    private int d = 1;
    private int a = 2;

    // 定义一个成员内部类
    public class Inner2
    {
        private int a = 8;

        public void doSomething()
        {
            // 直接访问外部类对象
            System.out.println(d);
            System.out.println(a);// 直接访问a,则访问的是内部类里的a

            // 如何访问到外部类里的a呢?
            System.out.println(MemberInner.this.a);
        }

    }

}

public class MemberInnerClassTest
{

    public static void main(String[] args)
    {

        // 创建成员内部类的对象
        // 需要先创建外部类的实例
        MemberInner.Inner2 inner = new MemberInner().new Inner2();

        inner.doSomething();
    }
}

3. 匿名内部类

3.1 就是没有名字的局部内部类。

3.2 与局部内部类不同的是,匿名内部类的类必须是预先定义好的已存在的类或接口。

3.3 匿名内部类隐式地继承了一个父类或者实现了一个接口。

3.4 因为没名字,因而默认只有无参数的构造函数,如果需要参数的,则需要该类有带参数的构造函数。例如:

public class Outer {
	public static void main(String[] args) {
		Outer outer = new Outer();
		Inner inner = outer.getInner("Inner", "gz");
		System.out.println(inner.getName());
	}

	public Inner getInner(final String name, String city) {
		// 注意这里的形参city,由于它没有被匿名内部类直接使用,而是被抽象类Inner的构造函数所使用,所以不必定义为final。
		return new Inner(name, city) {
			private String nameStr = name;

			public String getName() {
				return nameStr;
			}
		};
	}
}

abstract class Inner {
	Inner(String name, String city) {
		System.out.println(city);
	}

	abstract String getName();
}

例子:

package com.learnjava.innerclass;

import java.util.Date;

public class AnonymouseInnerClass
{

    @SuppressWarnings("deprecation")
    public String getDate(Date date)
    {
        return date.toLocaleString();

    }

    public static void main(String[] args)
    {
        AnonymouseInnerClass test = new AnonymouseInnerClass();

        // 打印日期:
        String str = test.getDate(new Date());
        System.out.println(str);
        System.out.println("----------------");

        // 使用匿名内部类
        String str2 = test.getDate(new Date()
        {
        });// 使用了花括号,但是不填入内容,执行结果和上面的完全一致
            // 生成了一个继承了Date类的子类的对象
        System.out.println(str2);
        System.out.println("----------------");

        // 使用匿名内部类,并且重写父类中的方法
        String str3 = test.getDate(new Date()
        {

            // 重写父类中的方法
            @Override
            @Deprecated
            public String toLocaleString()
            {
                return "Hello: " + super.toLocaleString();
            }

        });

        System.out.println(str3);
    }
}

4. 静态内部类

4.1 就是静态的成员内部类。定义时加上static。

4.2 不能和外部类有相同的名字。

4.3 只可以访问外部类的静态成员和静态方法,包括私有的。

4.4 可以直接引用Outer.Inner,即不需要创建外部类。

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

package com.learnjava.innerclass;

class StaticInner
{
    private static int a = 4;

    // 静态内部类
    public static class Inner
    {
        public void test()
        {
            // 静态内部类可以访问外部类的静态成员
            // 并且它只能访问静态的
            System.out.println(a);
        }

    }
}

public class StaticInnerClassTest
{

    public static void main(String[] args)
    {
        StaticInner.Inner inner = new StaticInner.Inner();
        inner.test();
    }
}

你可能感兴趣的:(Java内部类详解(二))