内部类
一、内部类的概念
定义在类中或接口中的类称之为内部类。
如果某个类只在另一个类中或另一个类的某个方法中使用,而不希望在整个项目中单独定义这个类,则可以通过定义内部类的方式,将这个类定义在需要使用它的类的内部或者该类方法的内部。
二、内部类的分类
内部类分为方法内部类、成员内部类、静态内部类和匿名内部类。
1.方法内部类
方法内部类的定义:在一个方法的内部定义的类,称之为方法内部类。方法内部类只能在当前定义到方法的结尾之间内能够被使用。
如果某个类只在某个方法内部使用到,则可以将该类声明在方法内,限定其使用的范围。
方法内部类的特点;
- 可以具有成员变量和成员属性
- 不能有静态变量和静态方法。因为此时内部类的寄生环境——外部类的方法还未生成,静态变量和静态方法不能访问。
- 可以声明静态常量。常量放置在常量区。
- 可以继承其他类或者实现接口。
- 可以使用外部类的成员属性和成员方法。
- Jdk8之前不能访问包裹当前内部类的方法中定义的局部属性,除非将其声明为final;Jdk8之后可以访问了,但不能对该值进行修改,如果进行修改,访问会报错。即:内部类可以访问外部类的变量,外部类的变量不可以修改(通常修饰为final)。
class Person { private String name; public void say() { System.out.println("说..."); } //方法内部类 public void eat() { String food = "羊肉串"; //方法内部类 class Cooker { //1.可以具有成员变量和成员方法 private String tool = "菜刀"; //2.可以有静态常量,不能有静态变量和方法 private static final String name = "张三"; public void cook() { System.out.println("厨师使用"+ tool + "做菜给" + name +"吃" + food); //5.可以调用外部方法 say(); } } //6. 内部类访问方法内的成员变量,该变量不能修改 //food = "牛肉串"; Cooker cooker= new Cooker(); cooker.cook(); System.out.println("吃..."); //4.可以继承和实现接口 class SichuanCooker extends Cooker {} } }
2.成员内部类
定义在一个类内部,可以当做类的一个成员使用的内部类称之为成员内部类。
用法:如果某个类内部还需要具有一个类结构,且需要外部类作为环境存在,则可以定义成员内部类。
成员内部类的特征:
- 成员内部类可以定义成员属性和成员方法。
- 成员内部类不可以定义静态变量和静态方法。
- 成员内部类可以定义静态常量。
- 成员内部类可以访问外部定义的成员属性,成员方法和静态方法。
- 可以通过访问权限修饰符修饰成员内部类。
- 可以在外部类中使用成员内部类。
- 在访问权限允许的情况下,可以在外部类之外通过对象来使用成员内部类。
- 可以继承类和实现接口。
class Outer { String Oname; public void eat(){}; //6.外部方法可以访问内部类 public void run(Inner inner){}; class Inner {
//3.成员内部类可以定义静态常量 private static final String name ="张安";
//1.成员内部类可以定义成员属性和成员方法
public void say() { System.out.println("说..." + Oname); //4.内部类可以访问外部类的方法 eat(); } } //8.一个内部类可以继承另外一个内部类 public class Inner2 extends Inner{}; } public class Demo02 { public static void main(String[] args) { Outer ou01 = new Outer(); //7.可以使用外部类对象.new Inner()方式创建内部类对象 Inner in01 = ou01.new Inner(); in01.say(); } }
3.静态内部类
用static修饰的成员内部类就是静态内部类;其本质上是成员内部类的静态版本。
静态内部类的特点:
- 可以定义成员属性和成员方法。
- 可以定义静态属性和静态方法。
- 静态内部类不可以访问外部类中非静态的成员属性和成员方法。
- 在外部类的内部,可以使用静态内部类。
- 可以通过访问权限修饰符修饰内部类。
- 在访问权限允许的情况下也可以在外部类之外通过【外部类.内部类】的方式访问静态内部类。
- 可以继承类和实现接口。
class Outer {
//4.在外部类可以使用静态内部类 private Inner in3 = null; static class Inner {
//2.可以定义静态成员和方法 private static String name;
//1.可以定义成员属性和方法 private int age; public static void say(){ System.out.println("说..."); } public static void say2() { System.out.println("说2..."); } } } public class StaticInnerClass { public static void main(String[] args) {
//7.可以通过外部类.内部类方法访问静态内部类 Outer.Inner inner = new Outer.Inner(); } }
4.匿名内部类
定义: 当new一个类(或接口)之后,在其后紧跟一个大括号,此时new的不是这个类或接口;而是创建了这个类或接口的匿名的子类(或者匿名实现类),其中大括号内为子类(或匿名实现类)的实现代码,new出来的是这个匿名内部类的对象。
用法:抽象类、普通类、接口都可以使用匿名内部类的用法;
匿名内部类的好处:内名内部类用起来减少了类的声明,简单方便,使用场景较多。
** * 匿名内部类 * @author Administrator * */ abstract class Car { public abstract void run(); } //抽象类的实现类 class Automobile extends Car { @Override public void run() { System.out.println("以60km/h速度跑..."); } } class TransDemo { public void trans(Car car) { System.out.println("准备货物..."); System.out.println("发送货物..."); //传输方法 car.run(); System.out.println("接收货物..."); System.out.println("卸载货物..."); } } interface Info01{ public void mx(); } public class Demo04 { public static void main(String[] args) { //1.--普通类 TransDemo tDemo = new TransDemo(); //传入子类 tDemo.trans(new Automobile()); //2.方法内部类 class Train extends Car { @Override public void run() { System.out.println("火车以160km/h速度跑..."); } } TransDemo tDemo1 = new TransDemo(); tDemo1.trans(new Train()); //3.匿名内部类 //--new 一个Car的子类的匿名内部类,该处相当于省去了class XXX extends //接口与之类似 TransDemo tDemo2 = new TransDemo(); tDemo2.trans(new Car() { @Override public void run() { System.out.println("飞车以1600km/h速度飞..."); } }); tDemo2.trans(new Automobile() { @Override public void run() { super.run(); } }); //4.实例化一个借口的匿名内部类 new Info01() { @Override public void mx() { System.out.println("mx..."); } }; } }