概述
很多时候我们创建类的对象的时候并不需要使用很多次,每次只使用一次,这个时候我们就可以使用内部类了。在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
内部类分为四种
- 成员内部类 2. 局部内部类 3. 匿名内部类
成员内部类
要访问内部类,可以通过创建外部类的对象,然后创建内部类的对象来实现。
嵌套类有两种类型:
- 非静态内部类
- 静态内部类
非静态内部类
非静态类内部类声明
public class OuterClass {
private int id;
public String name;
private void privateMethod() {
System.out.println("OuterClass private method");
}
public void publicMethod() {
System.out.println("OuterClass public method");
}
/*
InnerClass 声明在OuterClass 内部的非静态内部类
- 内部类访问外部类的所有属性及方法
- 如果内部类有相同的属性,需要用外部类的this 的,直接声明的属性名称默认指向内部类属性
-
*/
class InnerClass {
private int id = 8;
public void callOuterId() {
System.out.println(id);
}
public void callInnerId() {
System.out.println(OuterClass.this.id);
}
//调用外部类的私有方法
public void callOuterPrivateMethod() {
privateMethod();
}
//调用外部类的共有方法
public void callOuterPublicMethod() {
publicMethod();
}
public void publicInner() {
System.out.println("public inner");
}
}
}
非静态内部类运用
public class InnerTest {
public static void main(String[] args) {
//声明外部类实例
OuterClass outerClass = new OuterClass();
/*内部非静态实例
- 使用类的内部类比必须先有外部类的实例对象,通过此对象new一个内部类对象
*/
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
//调用非静态类方法
innerClass.publicInner();//public inner
//内部类声明相同属性,属性外部类获取
innerClass.callOuterId();//8
//相同属性获取内部类属性
innerClass.callInnerId();//0
//通过内部类调用外部类私有方法
innerClass.callOuterPrivateMethod();//OuterClass private method
//通过内部类调用外部类公有方法
innerClass.callOuterPublicMethod();//OuterClass public method
}
}
小结
- 使用类的内部类比必须先有外部类的实例对象,通过此对象new一个内部类对象
- 内部类访问外部类的所有属性及方法
- 如果内部类有相同的属性,需要用外部类的this 的,直接声明的属性名称默认指向内部类属性
- 成员内部类不能声明静态属性和方法
静态内部类
用static修饰的内部类即静态内部类
//静态内部类
static class StaticInnerClass{
private String name;
private static int age;
//非静态方法
public void test(String name){
System.out.println(name);
System.out.println(this.name);
// System.out.println(OuterClass.this.name);
System.out.println(OuterClass.age);
System.out.println(StaticInnerClass.age);
//只能调用外部类的静态方法
OuterClass.privateStaticMethod();
OuterClass.publicStaticMethod();
//不能访问非静态方法
// OuterClass.publicMethod();
// OuterClass.privateMethod();
}
//静态方法
public static void staticTest(String name){
System.out.println(name);
// System.out.println(OuterClass.this.name);
//获取静态属性
System.out.println(StaticInnerClass.age);
System.out.println(OuterClass.age);
//只能调用外部类的静态方法
OuterClass.privateStaticMethod();
OuterClass.publicStaticMethod();
//不能访问非静态方法
// OuterClass.publicMethod();
// OuterClass.privateMethod();
}
}
小结
- 静态内部类可以直接被外部类实例化,不需要使用外部类的对象
- 静态内部类不能访问外部类的非静态属性及方法
局部内部类
在类的方法中生命一个类作为局部内部类
public class MethodClass {
private int id;
public void outerMethod(){
System.out.println("MethodClass outer method");
}
public static void outerStaticMethod(){
System.out.println("MethodClass outer static method");
}
public void method1(){
//在局部内部类中,如果要访问局部变量,那么该局部变量要用final修饰
//如果声明为常量,当局部内部类被实例化后,局部变量随着方法出栈消失,局部内部类调用找不到该局部变量
final int field1 = 1;
class InnerClass{
private int id;
public void innerMethod(){
System.out.println("MethodClass inner method");
//外部类属性
System.out.println(MethodClass.this.id);
//局部类属性
System.out.println(this.id);
//方法局部变量
System.out.println(field1);
//外部类方法
MethodClass.this.outerMethod();
//外部类静态方法
MethodClass.outerStaticMethod();
}
}
}
}
小结
- 在局部内部类中,如果要访问局部变量,那么该局部变量要用final修饰
- 需要在方法中创建并调用局部类的方法,等待外部类调用
匿名内部类
匿名内部类是使用最频繁的一种,即将只使用的一次的临时创建需要依赖父类或接口类的内部类
//声明父类或接口
public class Person {
}
interface Work {
void working();
}
在代码块中应用
public void test(){
//同理需要把局部变量变为常量给匿名类调用
final int age = 18;
new Person(){
public void doSomething(){
System.out.println(age);
System.out.println( "doing");
}
}.doSomething();
Work work = new Work() {
public void working(){
System.out.println( "doing");
}
};
work.working();
}
小结
- 创建匿名内部类需要依赖父类或接口类
- 匿名内部中我们不写出其构造器,因为设有名字。
- 匿名内部中除了重写上面的方法外,一般不会再写其他独有的方法因为从外部不直接调用到。