Java常用类(1)- 内部类
内部类的概念
概念:在一个类的内部再定义一个完整的类
特点:
//外部类Menber public class Member { private String name; public static void main(String[] args) { new Member().new body().getName(); } //内部类body class body{ public void getName(){ System.out.println(name); } } }
- 编译之后可以生成独立的字节码文件
- 内部类可直接访问外部类的私有属性,从而不破坏封装
- 可为外部类提供必要的内部功能组件
内部类的分类
成员内部类
- 在类的内部定义,与实例变量、实例方法同级别的类
- 外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象
package commonclass.innerclass; import java.lang.reflect.Method; //外部类Menber public class Member { //实例变量 private String name; //内部类body public class body{ //内部类方法 public void getName(){ System.out.println(name); } } }
import commonclass.innerclass.Member; public class Application { public static void main(String[] args) { //调用内部类方法 //方式一 //1.创建外部类对象 Member member = new Member(); //2.创建内部类对象 Member.body body = member.new body(); //方式二 Member.body body1 = new Member().new body(); //方式三直接调用 new Member().new body().getName(); //3.调用内部类方法 body.getName();//方式一调用 body1.getName();//方式二调用 } }
- 当外部类、内部类存在重名属性时,会优先访问内部类属性
- 当外部类、内部类存在重名属性时,想要访问外部类属性怎么办? 外部类.this.外部类属性
- 成员内部类不能定义静态成员,但是可以定义静态常量
静态内部类
- 不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员
- 只能直接访问外部类的静态成员,访问非静态成员需要先实例化外部类,再访问
- 当外部类、静态内部类存在重名静态属性时,想要访问外部类属性怎么办? 外部类.外部类属性
package commonclass.innerclass; //外部类 public class StaticClass { static String name = "李四"; static int age = 14; double score = 99.9; //静态内部类,它的级别和外部类一样; //静态内部类存在的意义就是供外部类使用 public static class Inner{ //静态成员 static String name = "张三"; public void getName(){ StaticClass staticClass = new StaticClass(); System.out.println(name); System.out.println(age); System.out.println(staticClass.score); System.out.println(staticClass.name); System.out.println(StaticClass.name); } } }
import commonclass.innerclass.Member; import commonclass.innerclass.StaticClass; public class Application { public static void main(String[] args) { StaticClass.Inner inner = new StaticClass.Inner(); inner.getName(); } }
局部内部类
- 定义在外部类方法中,作用范围和创建对象范围仅限于当前方法
- 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自动相当(简单来讲就是加载的方法和类加载的问题),方法中的变量必须为常量,jdk1.8之后默认在局部内部类中,将变量设置为常量
- 使用范围只有在当前方法中使用
- 局部内部类方法,最后需要将局部内部类实例化,在外部类的当前方法中调用。局部内部类才有意义
//外部类 public class LocalClass { //外部类参数 private String name = "张三"; public void print(){ //方法参数 int age = 20; //局部内部类 class Inner{ //局部内部类参数 double score = 99.9; //局部内部类方法 public void show(){ System.out.println(name); System.out.println(age); System.out.println(score); } } //实例化局部内部类 Inner inner = new Inner(); //调用局部内部类 inner.show(); } }
import commonclass.innerclass.LocalClass; public class Application { public static void main(String[] args) { //局部内部类只需要new外部类即可,调用外部类的方法,从而实现调用方法中的局部内部类 LocalClass localClass = new LocalClass(); localClass.print(); } }
匿名内部类
- 没有类名的局部内部类(一切特征都与局部内部类相同),可有理解为匿名内部类是局部内部类的简写方式
- 匿名内部类存在的前提是必须继承一个父类或者实现一个接口
- 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象
- 优点:减少代码量
- 缺点:可读性比较差
前置
package commonclass.innerclass; //接口 public interface UserService { void print(); }
package commonclass.innerclass; //父类 public class Person { public void printFather(){ } }
局部内部类重写接口以及父类的方法
package commonclass.innerclass; //外部类 public class AnonymousClass { //main方法 public static void main(String[] args) { //局部内部类-接口 class UserServiceImp implements UserService{ @Override public void print() { System.out.println("接口重写"); } } UserServiceImp userServiceImp = new UserServiceImp(); userServiceImp.print(); //局部内部类-父类 class Student extends Person{ //Alt+Insert选择Over.. Method重写父类方法 @Override public void printFather() { System.out.println("继承父类,父类方法重写"); super.printFather(); } } Student student = new Student(); student.printFather(); } }
匿名内部类重写接口以及父类的方法
package commonclass.innerclass; //外部类 public class AnonymousClass { //main方法 public static void main(String[] args) {
//匿名内部类-接口 UserService userService = new UserService(){ @Override public void print() { System.out.println("匿名内部类重写接口"); } }; userService.print();
//匿名内部类-父类 Person person = new Person(){ @Override public void printFather() { System.out.println("匿名内部类重写父类方法"); super.printFather(); } }; person.printFather(); } }
匿名内部类和局部内部类的比较