1、使用内部类的原因:
内部类可以独立的继承一个接口的实现,从而解决多继承问题;内部类可以有多个实例,并且可以访问外部类的信息;外部类中可以有多个内部类,实现不同的接口,扩展不同的功能;静态内部类可以不依赖外部类而独立存在;内部类提供了更好的封装。
java中内部类总共有四种,成员内部类、静态内部类、方法内部类和匿名内部类,其关系如下图所示。
2、成员内部类
(1)声明方法
class MemberInnerClass {
private int i = 1;
public static String j = "abc";
public class Inner {
public void doSomething() {
System.out.println(i);
System.out.println(j);
}
}
}
这里有一个注意的细节,作为外部类只能被public或者被默认权限修饰符修饰,不能写出来default
成员内部类:顾名思义可以类比于一个类的普通成员变量。可以被四种权限修饰符修饰;可以访问内部类的普通成员和静态成员。那么可以访问外部类的方法或者静态方法吗?
class MemberInnerClass {
private int i = 1;
public static String j = "abc";
public void do1(){
}
public static void do2(){
}
public class Inner {
public void doSomething() {
System.out.println(i);
System.out.println(j);
do1();
do2();
}
}
}
通过上面的代码,答案是很肯定的。成员内部类可以访问内部类的普通方法和静态方法。如果外部类的方法访问权限是private的尼?
答案当然也是可以访问的,因为private权限的意思是只限类的内部访问,而成员内部类不刚好就在类的内部嘛。
(2)使用方法
成员内部类的对象的创建依赖于外部类,必须先创建外部类对象。这也是一种安全机制。
public static void main(String[] args) {
MemberInnerClass memberInnerClass = new MemberInnerClass();
Inner in = memberInnerClass.new Inner();
}
当成员内部类中具有和外部类同名的方法或者属性时,需要通过如下的方式进行访问。
//这里想要输出外部类的i值,方法也是一样的。
System.out.println(MemberInnerClass.this.i);
成员内部类中不能定义static属性和方法。因为成员内部类依赖于外部对象,而静态方法和属性只依赖于类而存在,与编译原理矛盾。
3、静态内部类
(1)声明方法
public class StaticInnerClass {
private int i = 1;
public static String j = "abc";
public String do1() {
return "a";
}
private static void do2() {
}
static class Inner {
}
}
静态内部类从声明上来看就是在成员内部类的基础上加上static修饰符;这个很好理解,就像我们的普通方法和静态方法的关系一样。静态属性和成员不依赖对象,只和类有关;静态内部类也不依赖外部类对象,可以独立存在。如果就对编译原理有了解,就应该知道静态内部类肯定是不能访问外部类的非静态方法和属性的。但是如果想访问的话,可以通过创建外部类对象来进行方法。
static class Inner {
public void doSomethin(){
do2();
StaticInnerClass staticInnerClass = new StaticInnerClass();
staticInnerClass.do1();
}
}
如果内部类的静态属性或者方法与外部类相同,默认是访问内部类的属性和方法,可以通过类型修饰的形式,访问外部类的静态成员和方法。
static class Inner {
static int j = 2;
private static void do2() {
}
public void doSomethin() {
System.out.println(MemberInnerClass.j);
MemberInnerClass.do2();
}
}
(2)使用方法
public static void main(String[] args) {
Inner inner = new Inner();
inner.doSomethin();
}
不依赖外部类,可以直接创建对象。
4、方法内部类
(1)声明方法
public class MethodInnerClass {
public static void doSomething() {
class Inner {
}
}
}
public class MethodInnerClass {
public void doSomething() {
class Inner {
}
}
}
方法内部类可以声明在普通方法或者静态方法内部,其作用域只在方法内部,类似于方法中的局部变量,不可以被public、protected、private和static修饰;当方法内部类位于静态方法中时,只可以访问外部类的静态成员和方法,当有同名变量时,通过外部类.静态属性来访问;当方法内部类位于普通方法内部时,可以访问外部类的全部属性和方法,当有同名属性或者方法时,通过外部类.this.属性名来访问。
(2)使用方法
public class MethodInnerClass {
final static int i = 1;
int m = 3;
static int n = 5;
public static void doSomething() {
final int j = 2;
final int i = 3;
class Inner {
public void do1() {
System.out.println(n);
System.out.println(MethodInnerClass.i);
}
}
Inner inner = new Inner();
inner.do1();
}
public static void main(String[] args) {
MethodInnerClass.doSomething();
}
}
上面的例子中时,位于静态方法中的内部类的调用方法;如果是普通方法中的内部类,需要先创建外部类对象,再通过对象进行调用。
5、匿名内部类
在鄙人不长的java代码生涯中, 匿名内部类算是比较常见的一个内部类应 用,特别是在创建多线程的过程中。
匿名内部类只能使用一次,必须继承一个类或者实现一个接口。匿名内部类不能有静态属性和方法;匿名内部类没有构造函数。
* * 匿名内部类
-
- 主要用于编写监听器程序和多线程
-
- 唯一的没有构造方法的类
-
- 只能够访问外部类的final类型的变量和方法
*/
- 只能够访问外部类的final类型的变量和方法
public class AnonymousInnerClass {
static int a = 1;
public Inner getInnerClass(final int num, String str) {
return new Inner() {
int number = num + a;
@Override public int getNumber() {
return number;
}
};
}
public static void main(String[] args) {
AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass();
Inner inner = anonymousInnerClass.getInnerClass(2, "bob");
System.out.println(inner.getNumber());
}
}
interface Inner {
int getNumber();
}
好了,内部类终于总结完了,如果有错误的地方欢迎批评指正;如果其中某些对您有帮助,欢迎留言交流。