内部类是指在一个外部类内定义的类(可以在方法中定义),按照是否有类名分为有名内部类和匿名内部类。
有名内部类:
package com.test.csdn;
import com.test.csdn.Body.Heart;
//前面不能加public,因为一个java文件中不能有俩个public类
class Body{
//有名内部类
public class Heart{
public void beat() {
System.out.println("心脏在跳动");
}
}
//此方法也可以创建,其中this可以省略
{
Heart heart = this.new Heart();
heart.beat();
}
}
public class Test{
public static void main(String[] args) {
//先创建外部内对象
Body body = new Body();
//创建内部类
Heart heart = body.new Heart();
heart.beat();
}
}
匿名内部类:
package com.test.csdn;
class Mammal{
public void move() {
System.out.println("动物在移动");
}
public Mammal() {
}
}
public class Sea{
//调用父类无参构造方法
Mammal whale = new Mammal() {
public void move() {
System.out.println("鲸鱼游动");
}
};
public static void main(String[] args) {
}
}
抽象类:抽象类匿名内部类实质为抽象类的子类
package com.test.csdn;
abstract class Mammal{
abstract void move();
public Mammal(String name) {
System.out.println(name);
}
}
public class Sea{
//调用父类有参构造方法
Mammal whale = new Mammal("鲸鱼") {
@Override
public void move() {
System.out.println("鲸鱼游动");
}
};
public static void main(String[] args) {
}
}
接口:接口匿名内部类实质为接口的实现类。
package com.test.csdn;
interface Mammal{
abstract void move();
}
public class Sea{
Mammal whale = new Mammal() {
public void move() {
System.out.println("鲸鱼游动");
}
};
public static void main(String[] args) {
}
}
匿名内部类特点:
1.匿名内部类一定是接口的实现类(该实现类仅能实现一个接口)或类(普通类或抽象类)的子类;
2.匿名内部类不能有构造方法,但是可以通过非静态代码块初始化成员变量;
3.匿名内部类一定不能是抽象类;
4.可以在匿名内部类中添加新的属性和方法,但是这些属性和方法不能被上转型对象所调用,只能被非上转型对象方式创建的匿名内部类对象所调用,例如:
public class Test {
public static void main(String[] args) {
IMammal whale = new IMammal() {
public void breath() {
System.out.println("鲸鱼正在呼吸......");
}
@Override
public void move() {
System.out.println("鲸鱼靠鳍游动......");
}
};//此时匿名内部类对象为上转型对象
whale.breath();// 上转型对象无法调用新增的breath方法
}
}
interface IMammal {
void move();
}
public class Test {
public static void main(String[] args) {
new IMammal() {
public void breath() {
System.out.println("鲸鱼正在呼吸......");
}
@Override
public void move() {
System.out.println("鲸鱼靠鳍游动......");
}
}.breath();// 调用新增的breath方法
}
}
interface IMammal {
void move();
}
同一个匿名内部类对象只能调用一个新增的属性或方法,无法再调用实现的抽象方法、重写的方法或继承的方法,也无法调用继承的属性
按照是否有static修饰分为静态内部类和非静态内部类,有static修饰的为静态内部类,没有static修饰的为非静态内部类,上面所举例都是非静态内部类,下面来说说静态内部类
静态有名内部类:
下方代码为跨类使用,若是本类使用,则不需要new Body。
package com.test.csdn;
import com.test.csdn.Body.Heart;
class Body{
public static class Heart{
public void beat() {
System.out.println("心脏在跳动");
}
}
}
public class Test{
public static void main(String[] args) {
//仔细区别和非静态内部类创建对象的区别,这里采用类名
Heart heart = new Body.Heart();
heart.beat();
}
}
静态匿名内部类:
class Father {
public void eat() {
System.out.println("筷子吃饭....");
}
}
/**
* 外部类
*/
public class OutClass {
/**
* 匿名内部类
*/
static Father son = new Father(){
@Override
public void eat() {
System.out.println("筷子吃饭....");
}
};
}
如果为static内部类只能直接定义在外部类中,非static的内部类可以定义在main方法内,如下
package com.test.csdn;
public class OutClass {
public static void main(String[] args) {
}
static class InClass {
public void printInfo() {
System.out.println("有名内部类");
}
}
}
在非外部类中定义的内部类和局部变量一样,其使用范围从定义的位置开始到其所在直接语句块结束。
public class OutClass {
public static void main(String[] args) {
if(args!=null) {
class InClass{
}
}
InClass inClass = new InClass();//无法创建对象,因为内部类作用范围无法作用到这里
}
}
只有有名静态内部类中才允许有静态成员(静态属性、静态代码块和静态方法)。
内部类是一个独立的类:编译之后内部类会被编译成独立的.class文件,如果该内部类为有名内部类,则有名内部类字节码文件名为外部类的类名+$+内部类类名;如果为匿名内部类,则匿名内部类字节码文件名为外部类的类名+$+数字;
普通外部类、抽象类和接口可以有内部类(匿名的或有名的);
内部类可以直接定义在类中,也可以定义在方法或代码块中;其中直接定义在外部类中的内部类可以有public、protected、默认的和private四种访问权限修饰(普通外部类、接口和抽象类只能使用public和default修饰),也可以使用static修饰( static不能修饰普通外部类、接口和抽象类);但是定义在方法或代码块中的内部类不能有访问修饰符修饰,也不能有static修饰。
public class OutClass {
private String name;
class InClass{
{
System.out.println(name);
}
}
}
内部类可以访问外部类的所有访问权限的成员变量,如上图;
内部类暂时就到这里了,说实话,我自己都觉得有点难。。。。。。