成员内部类
简单概述代码举例讲解浅谈内部类 局部内部类
初步理解代码理解总结 匿名内部类
代码讲解 成员内部类 简单概述
简而言之就是定义在一个类内部的类
接下来讲点注意点,就举例子理解
1、方法内部不能定义方法,但类的内部可以再次定义类
2、包含类的特点,但也有成员属性的限制
3、外部类的修饰符只有 [public、默认的],但内部类的修饰限定符和成员属性一样,比如static、final
接下来详细的使用方法都会在代码中举例、注释
代码举例讲解package 内部类;public class Outer { private int num = 10; static int age = 20; public class Inner{ 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); }}