类的内部成员之五--内部类

一、概念

Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类。

二、分类

1.成员内部类(静态、非静态)

  • 就是位于外部类成员位置的类。与外部类的属性、方法并列。
  • 成员内部类作为外部类的成员,可以访问外部类的私有成员或属性。(即使将外部类声明为private,但是对于处于其内部的内部类还是可见的。)
  • 当内部类访问外部类时,可以不受访问控制符的影响,直接访问属性与方法
  • 当外部类变量与方法和内部类同名,内部类默认访问自己的成员变量或方法,引用外部变量使用时加类名.this:类名.this.变量名、类名.this.方法名()
  • 在其他类创建一类中的内部类:内部类 对象名 = new 外部类对象( ).new 内部类( )
  • 外部类不能直接使用内部类的成员和方法,可先创建内部类的对象,然后通过内部类的对象来访问其成员变量和方法。
    举例说明:
class Person{
	String name = "小明";
	int age;
	public void eat(){
		System.out.println("人:吃饭");
	}
	//静态成员内部类
	static class Dog{
		String name;
		int age;
		public void show(){
			System.out.println("卡拉是条狗");
//			eat();
		}
	}
	//非静态成员内部类
	class Bird{
		String name = "杜鹃";
		public Bird(){
			
		}
		public void sing(){
			System.out.println("我是一只小小鸟");
			Person.this.eat();//调用外部类的非静态属性
			eat();
			System.out.println(age);
		}
	}
}

(1)作为外部类的成员:

  • 调用外部类的结构
  • 可以被static修饰
  • 可以被4种不同的权限修饰

(2)作为一个类:

  • 类内可以定义属性、方法、构造器等
  • 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
  • 可以被abstract修饰

2.静态内部类

  • 静态内部类不能直接访问外部类的非静态成员,但可以通过 new 外部类().成员 的方式访问
  • 外部类的静态成员与内部类的成员名称相同,可通过“类名.静态成员”访问外部类的静态成员
  • 创建静态内部类的对象时,不需要通过外部类的对象,可以直接创建 内部类 对象名= new 内部类();

3.局部内部类内部类(方法内、代码块内、构造器内)

  • 定义在一个方法或者一个作用域里面的类。
  • 局部内部类中不可定义静态变量,可以访问外部类的局部变量(即方法内的变量),但是变量必须是final的。
  • 没有访问修饰符,但可以使用final 或 abstract修饰。
  • 不能在方法内部类中创建可变的局部变量。
  • 可以访问外围类的成员变量。如果是static方法,则只能访问static修饰的成员变量。

4.匿名内部类

  • 匿名内部类其实就是一个没有名字的方法内部类,所以它符合方法内部类的所有约束,
  • 使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
  • 匿名内部类是没有访问修饰符的
  • 匿名内部类中是不能定义构造函数的,因为没有类名。
  • 匿名内部类中不能存在任何的静态成员变量和静态方法。
  • 匿名内部类为局部内部类(即方法内部类),所以局部内部类的所有限制同样对匿名内部类生效。
  • 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
  • 当所在的方法的形参需要被内部类里面使用时,该形参必须为final。
    格式:
new 类名(参数) | 实现接口()
{
// 匿名内部类的类体部分
}

举例说明:

public class TestDemo {
   public static void main(String[] args) {
       Person per = new Person() {
           public void work() {// 匿名内部类自定义的方法work
               System.out.println("work方法调用");
           }
           @Override
           public void eat() {// 实现接口的的方法eat
               System.out.println("eat方法调用");
           }
       };
       per.eat();// 可调用
       per.work();// 出错,不能调用
   }
}
interface Person {
   public void eat();
}

这里per.eat()是可以正常调用的,但per.work()不能调用.因为 Person per = new Person()创建的是Person的对象,而非匿名内部类的对象。匿名内部类连名字都没有,无法实例化调用对象,但继承父类的方法和实现的方法是可以正常调用的,本例子中,匿名内部类实现了接口Person的eat方法,因此可以借助Person的对象去调用。
若你确实想调用匿名内部类的自定义的方法work(),当然也有方法:
(1)类似于eat方法的使用,先在Person接口中声明work()方法,再在匿名内部类中覆写此方法。
(2)其实匿名内部类中隐含一个匿名对象,通过该方法可以直接调用work()和eat()方法;代码修改如下:

public class TestDemo {
    public static void main(String[] args) {
        new Person() {
            public void work() {// 匿名内部类自定义的方法work
                System.out.println("work方法调用");
            }

            @Override
            public void eat() {// 实现接口的的方法eat
                System.out.println("eat方法调用");
            }
        }.work();// 直接调用匿名内部类的方法
    }
}
interface Person {
    public void eat();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~四时春~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值