我们把一个类放在另一类的内部定义 称为内部类(inner class)
内部类分为 成员内部类,匿名内部类,局部内部类
注意
内部类只是一个编译时概念,一旦我们编译成功,就会成为完全不同的两个类。对于一
个名为 Outer 的外部类和其内部定义的名为 Inner 的内部类。编译完成后会出现 Outer.class和 Outer$Inner.class 两个类的字节码文件。所以内部类是相对独立的一种存在,其成员变量/方法名可以和外部类的相同
【示例】内部类的定义和使用
/**外部类 Outer*/
class Outer {
private int age = 10;
public void show(){
System.out.println(age);//10
}
/**内部类 Inner*/
public class Inner {
//内部类中可以声明与外部类同名的属性与方法
private int age = 20;
public void show(){
System.out.println(age);//20
}
}
}
非静态内部类(外部类里使用非静态内部类和平时使用其他类没什么不同)
非静态内部类对象必须寄存在一个外部类对象里。因此,如果有一个非静态内部类对象那么一定存在对应的外部类对象。非静态内部类对象单独属于外部类的某个对象。
非静态内部类可以直接访问外部类的成员,但是外部类不能直接访问非静态内部类成员。
非静态内部类不能有静态方法、静态属性和静态初始化块。
成员变量访问要点:
* 内部类属性:this.变量名。
* 外部类属性:外部类名.this.变量名。
【示例】内部类中访问成员变量
/**外部类 Outer1*/
class Outer1 {
private int age = 10;
public void show(){
System.out.println(age);//10
}
/**内部类 Inner*/
public class Inner1 {
//内部类中可以声明与外部类同名的属性与方法
private int age = 20;
public void show(){
System.out.println(age);//20
System.out.println(Outer1.this.age); //10 访问外部类的普通属性
}
}
}
内部类的访问:
【示例】内部类的访问
/**
* 测试非静态内部类
*/
public class TestInnerClass1 {
public static void main(String[ ] args) {
//先创建外部类实例,然后使用该外部类实例创建内部类实例
Outer1.Inner1 inner = new Outer1().new Inner1();
inner.show();
}
}
静态内部类特点
定义方式:
static class ClassName {
//类体
}
使用要点:
【示例】静态内部类的访问
/*
测试静态内部类
*/
class Outer2{
private int a = 10;
private static int b = 20;
//相当于外部类的一个静态成员
static class Inner2{
public void test(){
// System.out.println(a); //静态内部类不能访问外部类的普通属性
System.out.println(b); //静态内部类可以访问外部类的静态属性
}
}
}
public class TestStaticInnerClass {
public static void main(String[ ] args) {
//通过 new 外部类名.内部类名() 来创建内部类对象
Outer2.Inner2 inner =new Outer2.Inner2();
inner.test();
}
}
适合那种只需要使用一次的类。比如:键盘监听操作等等。在安卓开发、awt、swing开发中常见。
匿名内部类特点
语法:
new 父类构造器(实参类表) \实现接口 () {
//匿名内部类类体!
}
【示例】匿名内部类的使用
/**
* 测试匿名内部类
*/
public class TestAnonymousInnerClass {
public void test1(A a) {
a.run();
}
public static void main(String[] args) {
TestAnonymousInnerClass tac = new
TestAnonymousInnerClass();
tac.test1(new A() {
@Override
public void run() {
System.out.println("匿名内部类测试! 我是新定义的 第一个匿名内部类!");
}
});
tac.test1(new A() {
@Override
public void run() {
System.out.println("我是新定义的第二个匿名内部类 ");
}
});
}
}
interface A {
void run();
}
// 实现关系下的匿名内部类:
interface Dao {
void show();
}
public class AnonymousDemo {
//编写回调方法 :callInner
public void callInner(){
// 接口关系下的匿名内部类
new Dao(){
//实现子类 但是没有名字 所以叫匿名内部类
@Override
public void show() {
System.out.println("接口方法...");
}
}.show();
}
}
// 测试:
public class Demo {
public static void main(String[] args) {
AnonymousDemo anonymousDemo = new AnonymousDemo();
anonymousDemo.callInner();
}
}
匿名内部类可用于给方法传递实参,演示如下:
interface Dao {
void show();
}
public class AnonymousDemo {
//编写回调方法:callInner 参数类型为接口Dao
private static void callInner(Dao d) {
d.show();
}
public static void main(String[] args) {
callInner(new Dao() {//接口回调
//实现子类 但是没有名字 所以叫匿名内部类
@Override
public void show() {
System.out.println("匿名内部类用于给方法传递实参");
}
});
}
}
或许有些难以理解,其实过程并不复杂。
说明:首先有一个接口,然后在使用的类中编写了一个方法(参数类型是接口对象),并使用接口中未实现的方法。
我们调用此方法直接构造一个接口对象传入,此时会自动生成一个此接口的子类(匿名内部类)实现接口中的方法。本质传入的类便是此时的匿名内部类。
注意
匿名内部类没有访问修饰符。
匿名内部类没有构造方法。因为它连名字都没有那又何来构造方法呢。
定义在方法内部的,作用域只限于本方法,称为局部内部类。
局部内部类在实际开发中应用很少。
局部内部类的特点
案例
public class Partial {
String name = "外部类的类名";
String type = "外部类的type属性";
private int item = 1;
public static void show() {
System.out.println("掉用外部类中的show方法");
}
public void print() {
System.out.println("调用外部类中的打印方法");
}
public void demo(){
String name = "外部类方法deme()内部的方法名";
String type = "外部类方法deme()内部的type属性";
/*编写在方法的内部的类称之为局部内部类
局部内部类不可使用权限修饰符 静态修饰符进行修饰 同局部变量相同
局部内部类与局部变量使用范围一样 在此方法内部
局部内部类可以直接访问方法中的属性 重名时使用参数传递完成访问*/
class Inner{
//局部内部类 可以访问方法外部类中属性和方法
String name = "局部类的类名";
public void showInner(String name){
show();
print();
System.out.println("我是:"+ type);
System.out.println("我是:"+ Partial.this.type);
System.out.println(item);
System.out.println("我是:" + this.name);
System.out.println("我是:" + name);
System.out.println("我是:" + Partial.this.name);
}
}
//局部内部类 创建对象 要在方法内部 局部内部类的外部声明
Inner inner = new Inner();
inner.showInner(name);
}
public static void main(String[] args) {
Partial partial = new Partial();
partial.demo();
}
}
【示例】方法中的内部类
/**
* 测试局部内部类
*/
public class TestLocalInnerClass {
public void show() {
//作用域仅限于该方法
class Inner3 {
public void fun() {
System.out.println("helloworld");
}
}
new Inner3().fun();
}
public static void main(String[ ] args) {
new TestLocalInnerClass().show();
}
}