Java 内部类学习

内部类:在别的类中定义的类

内部类的学习大纲:

1.内部类分类及说明

2.内部类的覆盖

3.内部类的重写

4.使用内部类的优势

Java内部类分类:
静态内部类(static inner class)
成员内部类(member inner class)
局部内部类(local inner class)
匿名内部类(anonymous inner class)

各个类的属性:

静态内部类(访问方式相当于静态方法):

a.创建静态内部类对象,不需要外部类对象。
b.不能从静态内部类对象中访问非静态的外部类对象成员。
c.接口中可以定义静态内部类

创建:
(方法一)StaticInner.Inner inner = new StaticInner.Inner();

(方法二)import note.StaticInner.Inner;
Inner inner = new Inner()

成员内部类(访问方式相当于成员方法)

能访问外部类中的全部成员变量和方法

2.普通内部类(成员内部类):
会得到外部类的所用成员的访问权限
.this和.new
.this:内部类获取外部类的对象可直接使用:OutClass.this;
.new: 创建内部类,需要使用外部类的对象 outObj.new InnerClass();
因为成员内部类对象需要使用外部类对象创建,所以持有该外部类对象,所以拥有外部类的所有成员访问权限。
访问权限:
private protected public 默认修饰内部类
private:只可在该外部类中声明和初始化该内部类
默认:只可在同包或者该外部类中声明和初始化内部类
protected:只可在同包,或者外部类的子类,或者该外部类中声明和初始化内部类
public:可在任何类中声明和初始化

对于访问权限不够的内部类,如何在别的类中声明和访问?
声明:可让内部类继承一个外部接口,通过外部接口对象接收内部类
访问:在外部类中定义方法返回该内部类对象

注意:
a.外部类可以访问内部类的任何访问权限的成员(可以访问内部类私有成员)。
b.普通内部类对象隐式的保存了一个引用,指向创建它的外围对象。
c.普通内部类对象不能有static方法和static字段

创建:要创建成员内部类就要先创建外部类(例如要想调用成员方法,必须先初始化一个对象是一样的道理)
MemberInner.Inner memberInner = new MemberInner().new Inner(); 正确、
//MemberInner.Inner memberInner = new MemberInner.Inner(); 错误:创建成员内部类要先创建外部类


局部内部类
局部内部类定义在方法中,比方法的范围还小。是内部类中最少用到的一种类型。

像局部变量一样,不能被public, protected, private和static修饰。

只能访问方法中定义的final类型的局部变量,也可以访问外部类中的成员变量和成员方法

局部内部类在方法中定义,所以只能在方法中使用,即只能在方法当中生成局部内部类的实例并且调用其方法。

使用局部内部类的理由:
a.实现某个接口,于是可以返回对其的引用
b.创建一个辅助的类来帮你解决问题,并且不希望这个类是公用的。
c.局部内部类不能有访问控制权限,与局部变量相通。

注意:
作用域之外不能声明局部内部类。
局部内部类其实与普通类编译都是一样的,只是在作用之外不可用而已。


匿名内部类
匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。

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

匿名内部类使用得比较多,通常是作为一个方法参数。

public ParaUsb getParaUsb(String name){
return new ParaUsb(name){

String TAG = "OutClass -> ParaUsb:";
String para = getName();

@Override
String convert() {
return TAG + "VGA"; // + name 匿名内部类使用外部类的成员变量,该变量必须是final,否则不可用
}
};
}

注意:
a.匿名内部类使用外部类的成员变量,该变量必须是final,否则不可用
b.可以将外部类的成员通过构造器传给匿名内部类的基类,在该基类中通过方法返回该外部类的成员,即可访问外部类的非final成员
c.匿名内部类与正常的继承相比,限制更大(通过构造器继承,只有一个构造器),因为匿名内部类即可以继承父类也可以实现接口,但是不能两者兼备,实现接口也只能实现一个接口。
6.多层内部类:
多层内部类 :一个类无论嵌套多少层内部类,该内部类能透明的访问所有它嵌入的外部类的所有成员。
class OutClass{
void printfOutClass();
class InnerA{
private String name = "A class";
void a(){}
class InnerB{
private String name = "B class";
void b(){
a();
printfOutClass();
}
}
}
}

7.内部类的继承
如果想用一个普通类去继承另一个类的内部类,必须在该普通类的构造方法里加上另一个类的引用
因为:内部类必须要持有外部类的引用。

class ExtendInnerClass{
public ExtendInnerClass(OutClass outClass){
outClass.super(); //构造函数需要连接外部类,不调用,不能通过编译器
}
}

8.内部类的重写:
class A{
InnerA innerA;
public A(){
System.out.println("A");
innerA = new InnerA();
}

public void printf(){
innerA.printf();
}

public void insertInnerA(InnerA a){
innerA = a;
}

class InnerA{
public InnerA(){
System.out.println("InnerA");
}

void printf(){
System.out.println("InnerA");
}
}
}

/**
* 重写内部类不起作用
*/
class ExtendA extends A{
public class InnerA {
public InnerA(){
System.out.println("ExtendA InnerA");
}
void printf(){
System.out.println("ExtendA InnerA");
}
}
public void printf(){
innerA.printf();
}
}

/**
* 重写内部类并且可以使用的方式
*/
class ExtendA2 extends A{
public ExtendA2(){
insertInnerA(new InnerA()); //使用继承的当前内部类替换父类中的内部类
}
public class InnerA extends A.InnerA{
public InnerA(){
System.out.println("ExtendA2 InnerA");
}

void printf(){
System.out.println("ExtendA2 InnerA");
}
}
public void printf(){
innerA.printf();
}
}

public class OverrideInnerClass {
public static void main(String[] args){
ExtendA a = new ExtendA();
a.printf();
ExtendA2 a2 = new ExtendA2();
a2.printf();
}
}

代码:

package note;

import note.StaticInner.Inner;

/**
* 静态内部类{@docRoot 静态内部类只能访问外部类的静态成员变量和静态方法(无论private/public)}
* @author zhaobing
*
*/
class StaticInner{

/**
* 定义一个静态变量,让静态内部类访问
*/
private static String name="StaticInner";

public static void printfExternal(){
System.out.println("external class static method");
}

static class Inner{
void printf(){
System.out.println("this is external class static member (name):" + name);
printfExternal();
}
}
}

/**
* 成员内部类{@docRoot 静态内部类只能访问外部类的成员变量和方法(无论private/public)}
* @author zhaobing
*
*/
class MemberInner{

private String name = "MemberInner";

public void printfExternal(){
System.out.println("External class method");
}

class Inner{

public void printf(){
System.out.println("this is external class member (name):" + name);
printfExternal();
}
}
}

/**
* 在外部类的某一方法中定义类
* 局部内部类 {@docRoot 静外部类的成员变量和方法(无论private/public) 但访问外部类该方法中的非final变量}
* @author zhaobing
*
*/
class LocalInner{

private String name = "LocalInner";
private int age = 10;
private void p(){
System.out.println("test");
}

public void printfExternal(){
int b=3;
final int c=1;

class Inner{
public void printf(String name){
System.out.println(name+c+age);
// System.out.println(name+a+age); 报错 不能访问方法中非final变量
p();
}
}
Inner inner = new Inner();
inner.printf(name);
System.out.println("External class method");

}
}

public class InnerClassDemo {

public static void main(String args[]){

/**
* 静态内部类测试
*/
Inner staticInner=new Inner();
staticInner.printf();
// StaticInner.Inner inner = new StaticInner.Inner(); 也可以使用这种方式创建,这种方式创建的时候不需要import导入

/**
* 成员内部类测试
*/
// MemberInner.Inner memberInner = new MemberInner.Inner(); 错误:创建成员内部类要先创建外部类
MemberInner.Inner memberInner = new MemberInner().new Inner();
memberInner.printf();

/**
* 成员内部类测试
*/
LocalInner localInner = new LocalInner();
localInner.printfExternal();

/**
* 匿名内部类
*/
AnonymousInner anonymousInner = new AnonymousInner();
anonymousInner.printf(new Integer(3));
}

}

class AnonymousInner{

private String name = "AnonymousInner";

public void printf(Integer i){
System.out.println("i:"+i);
}

}

原文地址:https://www.cnblogs.com/x-bing/p/4549792.html