java是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaEE, JavaME, JavaSE)的总称。本站提供基于Java框架struts,spring,hibernate等的桌面应用、web交互及移动终端的开发技巧与资料

保持永久学习的心态,将成就一个优秀的你,来 继续搞起java知识。

一、定义

在一个类的内部定义的一个类,这个定义在内部的类叫内部类

二、 1、内部类作为外部类的一个"成员",可以被外部类的其它的成员访问。也可以使用各种访问修饰符。

2、内部类:可以访问外部类的成员(即使外部类成员是私有的),也可以访问本类的成员;

3、内部类的常用修饰符:

1.可用修饰符:四种访问权限修饰符、static、final、abstract(外部类可以不是abstract),可以调用外部类的属性

2.private:此内部类被私有,只能在外部类内部被实例化;

static :在其它类中实例化内部类对象,就不需要外部类对象了;

1.被静态修饰的成员内部类只能访问外部类的静态成员

2.内部类被静态修饰后的方法

可以是静态方法

可以是非静态方法

三、内部类分类:

1、java内部类分为:成员内部类、方法内部类、静态内部类,匿名内部类

2、成员内部类:定义在外部类的成员位置,跟外部类的其他成员是并列关系

①具有成员的特征:可以有四种访问修饰符、static和final修饰

②具有类的特征:abstract,可以有具体成员和方法、构造器

3、 成员内部类定义:

classOuter {

classInner{}

}

编译上述代码会产生两个文件:Outer.class和Outer$Inner.class

3/1 成员内部类不能含有静态变量或静态方法,因为实例化成员内部类对象要先实例化外部类对象。如果一个内部类的成员变量被声明为static的,则这个内部类也要被声明为static的,这个内部类就成为了静态内部类

2/3 创建成员内部类的对象

①创建静态内部类的对象可以直接通过 外部类.内部类 引用名 = new 外部内.内部内的构造方法,如Outer.Inneroi = new Outer.Inner();

②创建非静态内部类的对象

Outer out = new Outer();

Outer.Inner in = out.new Inner();

in.show();

或者

Outer.Inner in = new Outer().new Inner();

in.show();

3/2 成员内部类可以直接访问外部类包括private型的所有成员,外部类要访问内部类成员要先创建内部类的对象

3/3 在成员内部类要引用外部类对象时,使用outer.this来表示外部类对象

4、局部内部类:定义在某个方法的内部。只有在内部类的方法时才会创建内部类的对象

常用形式,定义一个方法,使其返回类型为某个类或接口的对象,这个类或接口在这个方法内部定义,实现接口或类

把类放在方法内

比较少用的形式:

classOuter {

publicvoid doSomething(){

classInner{

publicvoid seeOuter(){

}

}

}

}

常用形式:

class Outer{

//定义一个返回类型为某个类或接口的方法

public Interfunction(){

//class Studentimplements Inter{

String name;

int age;

}

//返回实现类的对象

return newStudent();

}

}

4/1 方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。

4/2 方法内部类对象不能使用该内部类所在方法的非final局部变量。

因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。

下面是完整的例子:

classOuter {

publicvoid doSomething(){

finalint a =10;

classInner{

publicvoid seeOuter(){

System.out.println(a);

}

}

Innerin = new Inner();

in.seeOuter();

}

publicstatic void main(String[] args) {

Outerout = new Outer();

out.doSomething();

}

}

4/3 方法内部类不能定义成static类型的,其成员变量也不能是static的

5、匿名内部类

5/1 定义

顾名思义,没有名字的内部类。表面上看起来它们似乎有名字,实际那不是它们的名字。

正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口

5/2 声明

当程序中使用匿名内部类时,在定义匿名内部类的地方往往直接创建该类的一个对象。匿名内部类的声明格式如下:

new ParentName(){

...// 内部类的定义

}

例:

class Outer{

public Interfunction(){

return new Inter{

};

}

}

5/3 使用匿名内部类的情况

3/1 只用到类的一个实例 。

3/2 类在定义后马上用到。

3/3 类非常小(SUN推荐是在4行代码以下)

3/4 给类命名并不会导致你的代码更容易被理解。

5/4 匿名内部类的使用原则

4/1 匿名内部类不能有构造方法。

4/2 匿名内部类不能定义任何静态成员、静态方法。

4/3 匿名内部类不能是public,protected,private,static。

4/4 只能创建匿名内部类的一个实例。

4/5 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。

4/6 因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。

5/5 匿名内部类的应用:

4/5/1 当我们需要调用某个方法,这个方法需要一个某接口类型的实参。我们为了调用这个方法,可

以先定义一个这个接口的子类,然后实例化这个子类对象,并将引用传递到这个方法;

4/5/2 如果,这个子类,只在调用这个方法时使用,其他地方不需要用到这个子类,这时,可以不用

定义这个子类。在调用这个方法时,使用"匿名内部类"的方式。那么这个子类就没有了"性"。

6、匿名内部类的使用实例

实例1:不使用匿名内部类来实现抽象方法

12

3

4

5

6

7

8

9

10

11

12

13

14

15

16

abstract class Person {

public abstract void eat();

}

class Child extends Person {

public void eat() {

System.out.println("eat something");

}

}

public class Demo {

public static void main(String[] args) {

Person p = new Child();

p.eat();

}

}

运行结果:eatsomething

可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用

但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?

这个时候就引入了匿名内部类

实例2:匿名内部类的基本实现

12

3

4

5

6

7

8

9

10

11

12

13

14

abstract class Person {

public abstract void eat();

}

public class Demo {

public static void main(String[] args) {

Person p = new Person() {

public void eat() {

System.out.println("eat something");

}

};

p.eat();

}

}

运行结果:eat something

可以看到,我们直接将抽象类Person中的方法在大括号中实现了

这样便可以省略一个类的书写

并且,匿名内部类还能用于接口上

实例3:在接口上使用匿名内部类

interface Person{

public void eat();

}

public class Demo{

public static void main(String[]args) {

Personp = new Person() {

public void eat(){

System.out.println("eatsomething");

}

};

p.eat();

}

}

运行结果:eat something

由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现

最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口

实例4:Thread类的匿名内部类实现

public class Demo{

public static void main(String[]args) {

Threadt = new Thread() {

public void run(){

for (int i= 1; i <= 5; i++) {

System.out.print(i+ " ");

}

}

};

t.start();

}

}

运行结果:1 2 3 4 5

实例5:Runnable接口的匿名内部类实现

12

3

4

5

6

7

8

9

10

11

12

13

public class Demo {

public static void main(String[] args) {

Runnable r = new Runnable() {

public void run() {

for (int i = 1; i <= 5; i++) {

System.out.print(i + " ");

}

}

};

Thread t = new Thread(r);

t.start();

}

}

运行结果:1 2 3 4 5

四、内部类的共性

1、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号 。

2、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的 。

3、内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量

五、内部类的常用修饰符

1、可用修饰符:四中访问权限修饰符、static、final、abstract(外部类可以不是abstract)

2、内部类被私有化,则只能在外部类内部被实例化

3、内部类被static修饰,在其他类中实例化内部类对象,不需要外部类对象

4、内部类被static修饰后可以有静态成员和非静态成员,但若内部类中有由静态成员,则内部类必须是静态的

5、被static修饰的成员内部类只能访问外部类的静态成员

六、为什么需要内部类

典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。使用内部类最吸引人的原因是:

每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。

java

因为水平有限,难免有疏忽或者不准确的地方,希望大家能够直接指出来,我会及时改正。一切为了知识的分享。

后续会有更多的精彩的内容分享给大家。