1. 成员内部类
- 定义格式:
修饰符 class外部类名称{
修饰符 class 内部类名称{
}
} - 调用方式:
- 通过外部类的方法来创建内部类对象,然后通过创建的外部类对象来实现对内部类的调用。
class Outer{
private Inner inner=null;
class Inner{
public void show_inner(){
System.out.println(a);
}
public Inner getInner(){
if(inner==null){
inner=new Inner();
return inner;
}
}
}
public class Test{
public static void main(String[]args){
Outer outer=new Outer();
Outer.Inner inner=outer.getInner();
}
}
‘
2. 通过建立外部类.内部类对象来访问
class Outer{
private Inner inner=null;
class Inner{
public void show_inner(){
System.out.println(a);
}
}
}
public class Test{
public static void main(String[]args){
Outer outer=new Outer();
Outer.Inner inner=outer.new Inner();
}
}
- 访问权限
内部类拥有的访问权限为:public、protected、private,如果成员内部类用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问,如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问,如果用默认访问权限,则只能在同一个包下访问。
2. 局部内部类
- 定义
局部内部类是定义在一个方法或者作用域里面的类,与成员内部类的区别在于,局部内部类的访问权限仅限于方法内或者该作用域内 - 举例
class Outer{
public void method(){
final int age=20;
class LocalInner{
public void method(){
System.out.println(age);
}
}
new LocalInner().method();
}
public static void main(String[]args){
Outer outer=new Outer();
outer.method();
}
}
- 注意:
- 无法在外部去创建局部内部类的实例对象,因为局部内部类是定义在方法中的,而方法是需要所在类的对象去调用的
- 局部内部类如果要去访问局部变量,那么局部变量必须声明为final类型
- 局部内部类就像方法里的一个局部变量一样,不能有public、protected、private以及static修饰符
3. 匿名内部类
- 格式:
接口名称 对象名=new 接口名称(){里面的内容为复写抽象方法}; - 例子:
//不使用匿名内部类
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();
}
}
//########################################
//使用匿名内部类
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();
}
}
- 注意:只要一个类是抽象的或者是一个接口,那么其子类中的方法都可以使用匿名内部类来实现
- 匿名对象
abstract class Person {
public abstract void eat();
}
public class Demo {
public static void main(String[] args) {
new Person() {
public void eat() {
System.out.println("eat something");
}
}.eat();
}
}
4. 静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类前多了一个关键字static,静态内部类不需要依赖于外部类,其不能使用外部类的非static成员变量或者方法。
class Outer{
static int a=3;
static class Inner{
public void show_inner(){
System.out.println(a);
}
5. 疑问
- 为什么成员内部类可以无条件访问外部类的成员?
虽然定义的内部类的构造器是无参构造器,编译器还是会默认添加一个参数,该参数的类型为指向外部类对象的一个引用,所以可以在成员内部类中随意访问外部类的成员。 - 为什么局部内部类和匿名内部类只能访问局部final变量?
匿名内部类的构造器有两个参数,一个指向外部类对象的引用,一个是变量,也就是如果局部变量的值在编译期间就可以确定,则直接在匿名内部类里创建一个拷贝,如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值。由此,局部变量和匿名内部类中的变量根本就不是同一个