七、内部类

成员内部类

简单概述

简而言之就是定义在一个类内部的类

接下来讲点注意点,就举例子理解

1、方法内部不能定义方法,但类的内部可以再次定义类

2、包含类的特点,但也有成员属性的限制

3、外部类的修饰符只有 [public、默认的],但内部类的修饰限定符和成员属性一样,比如static、final

接下来详细的使用方法都会在代码中举例、注释

代码举例讲解

package 内部类;
/*
整理理解的话,内部类就是
类+类成员属性
既满足类的含有的功能
也满足成员属性的一些限制,比如修饰符;静态、非静态的访问;变量的就近原则...
 */
public class Outer {
    private int num = 10;
    static int age = 20;
    
    public class Inner{
        /*
        内部类注意点:
        1、访问修饰符和成员变量成员方法一样
        2、也可以用static修饰
        3、但同样满足静态不能访问非静态,非静态可以访问静态,前面讲过
        4、非静态内部类不能定义静态方法和变量
        5、内部类可以访问外部类元素
         */
        private int age;
        private int num;
        public void methodInner(){
            System.out.println("这是内部类方法");
            System.out.println(num);//优先访问靠近的,都是一样的
            System.out.println(age);
            //成员与方法的调用一样
            System.out.println(this.age);//指的是内部类的变量
            System.out.println(Outer.this.num);//是外部类的变量
            System.out.println(Outer.age);//非静态成员可以访问静态成员

        }
    }
    //内部类之间的继承,
    // 当然接口的继承都是可以的,对于其他类、外部类(没必要,本来就可以访问外部类元素)都是可以继承的
    //抽象类、接口哪些就不一一举例了,基本都是一样的
    public class SubInner extends Inner{
        @Override//重写,都是满足类的功能的
        public void methodInner() {
            super.methodInner();
        }
    }
    public void method1(){
        //这里可以创建内部类,但是静态方法,就不能创建非静态内部类,可以考虑内存的加载
        //但静态方法可以通过创建外部类来创建内部类,即主方法的演示
        System.out.println("这是外部类方法");
        Inner inner = new Inner();//可以创建内部类成员、用内部类成员调用相应数据
        inner.methodInner();
    }

    public static void main(String[] args) {
        Outer test1 = new Outer();
        test1.method1();
        //如果想要创建内部类对象
        //静态访问非静态,需要借用外部类
        Outer.Inner inner = test1.new Inner();
        //如果访问别的类中的静态内部类Outer.Inner inner = new Outer.Inner();
        //访问别的类中的非静态内部类Outer.Inner inner = outer.new Inner();
        //如果内部类是静态的可以这样创建内部类:Inner inner = new Inner();静态之间是可以直接访问的

        inner.methodInner();
    }
}

浅谈内部类

根据上面知识点总结一下

非静态内部类的特点
  在非静态内部类中不能定义static修饰的属性,方法,代码块。
  在非静态内部类中可以调用外部类的属性,方法。
  在非静态内部类的方法中可以调用外部类的属性,方法,满足就近原则。
  如果出现同名?怎么区分?外部类的属性或方法外部类的名 . this.属性|方法();
  可以访间外部类static修饰的属性或方法吗?可以的
 如何调用非静态内部的属性或方法呢?
  1)在外部类的中进行?
    外部类非静态方法:直接创建内部类的对象,然后通过对象进行调用属性或方法
    外部类静态方法:创建外部类的对象,再根据外部类对象.new 内部类()语法创建内部类对象通过内部类对象调用属性和方法
  2)在其他的类中如何调用?
创建外部类的对象,再根据外部类对象. new内部类()语法创建内部类对象通过内部类对象调用属性和方法


静态内部类的特点
  static修饰的,可以再静态内部类中使用static关键字来修饰属性和方法,以及代码块。
  再静态内部类中,只能调用外部类中静态的属性和方法。在静态内部类中不能使用外部类名 . this
  再静态内部类中不能使用this关键字?
    错误的,再静态内部类中可以定义非静态的方法。可以再非静态方法中使用this关键字,调用该静态内部类中定义的非静态属性和方法。但是不能使用外部类 . this
  如果想调用静态内部类中的属性和方法:
    如果是静态成员,可以直接通过静态内部类名,进行调用, 如果再其 他类中可以通过外部类.内部类.静态成员
    如果是非静态成员,必须得创建静态内部类的对象通过对象名。进行调用:外部类.内部类对象名= new 外部类 .内部类();
注意:内部类可以创建对象也是因为在内部类中有构造方法。如果显示添加带参构造方法,new对象的时候,必须传递参数。

基本了解了之后,我们研究一下内部类的好处。要我说也就是解决的java中单继承的弊端,每一个内部类都可以独自继承一个类、接口、抽象类,这样就可以丰富类的功能,但说的很不专业,还是在上一下专业术语。

为什么要使用内部类?在《Think in java》中有这样一句话:使用内部类最吸引人的原因是:每个 内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实 现,对于内部类都没有影响。 在我们程序设计中有时候会存在一些使用接口很难解决的问题,这个 时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问 题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。使 用内部类最大的优点就在于它能够非常好的解决多重继承的问题,但是如果我们不需要解决多重继 承问题,那么我们自然可以使用其他的编码方式,但是使用内部类还能够为我们带来如下特性(摘 自《Think in java》):

  1、内部类可以用多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独 立。

  2、在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,或者继承同一个类。

  3、创建内部类对象的时刻并不依赖于外围类对象的创建。

  4、内部类并没有令人迷惑的“is-a”关系,他就是一个独立的实体。

  5、内部类提供了更好的封装,除了该外围类,其他类都不能访问。

成员内部类也是最普通的内部类,它是外围类的一个成员,所以他是可以无限制的访问外围类的所 有 成员属性和方法,尽管是private的,但是外围类要访问内部类的成员属性和方法则需要通过内 部类实例来访问.

局部内部类

初步理解

基本一样,这里只提一下不同点

1、定义在代码块中,只有在代码块中有效,和局部变量一样

2、没有访问修饰符,没有static,和局部变量是一样的

3、相关特性和局部变量一致,也包含类的属性
4、局部内部类无法访问同名局部变量

代码理解

package 内部类;

public class Part {
    {
        class inner1{

        }
    }
    int age = 44;
    static int name = 33;
    static {
        int name = 22;
        class inner2{
            public int name = 12;
            int age = 13;
            public void test(){
                System.out.println(name);
                System.out.println();//局部内部类无法访问同名局部变量
                System.out.println(Part.name);
//                System.out.println(Part.this.age);
                //System.out.println(Part.age);静态不能访问非静态
            }
        }
        inner2 i = new inner2();
        i.test();
    }
    public void f(){
        class inner3{

        }
    }

    public static void main(String[] args) {
        class inner4{

        }
    }
}

总结

局部内部类:
 位置在方法中,代码块中,构造方法中。作用范围也只能在声明他的语句块中。
 局部内部类不能用访问修饰符修饰,也不能用static修饰。所以局部 内部类中定义的属性和方法以及代码块是非静态的。
 局部内部类可以访问外部类中声明的属性和方法。[看局部内部类所在的块是否是静态决定能够访问哪些成员]
 如果使用?创建局部内部类的对象,通过局部内部类对象名。进行访问.
 局部内部类的方法可以访问所在的块声明的局部变量,在jdk1 .7前该变量必须是final修饰的,但是jdk8后不要求了。

匿名内部类

匿名类,就是没有名称的类,其名称由Java编译器给出,一般是形如:外部类名称+$+匿名类顺 序,没有名称也就是其他地方就不能引用,不能实例化,只用一次,当然也就不能有构造器。 匿名类根据位于地方不同分为:成员匿名类和局部匿名类。

匿名类不能使用任何关键字和访问控制符,匿名类和局部类访问规则一样,只不过内部类显式的定 义了一个类,然后通过new的方式创建这个局部类实例,而匿名类直接new一个类实例,没有定义 这个类。匿名类最常见的方式就是回调模式的使用,通过默认实现一个接口创建一个匿名类然后, 然后new这个匿名类的实例。

代码讲解

先写一个接口

package 内部类;

public interface Inter {
    public void f();
}

匿名内部类的实现

package 内部类;

public class Test {
    public void test(Inter inter){//传进来的接口并没有实现
        inter.f();
    }
    public static void main(String[] args) {
        Test t = new Test();
        //方法一:只是用一次
        t.test(new Inter() {
            @Override
            public void f() {
                System.out.println("测试");
            }
        });
        //方法二:可以多次使用,所以接口没有实现的话,这种方法也是可以使用的
        Inter inter = new Inter() {
            @Override
            public void f() {
                System.out.println("测试");
            }
        };
        t.test(inter);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值