java内部类分为: 静态嵌套类、成员内部类、方法内部类、匿名内部类。
内部类的共性
(1)、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
(2)、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。
(3)、内部类声明成静态的,就不能随便的访问外部类的成员变量了,此时内部类只能访问外部类的静态成员变量。
静态嵌套类
package com.test.innerclass; class StaticInner { private static String info = "HelloWorld"; /** * 静态内部类 * 只能访问外部类的静态成员变量及方法 */ static class Inner { public String getInfo() { return info; } } } public class StaticInnerClassTest { public static void main(String[] args) { //获取静态内部类实例 StaticInner.Inner inner = new StaticInner.Inner(); //输出静态内部类类名 System.out.println(inner.getClass().getName());//com.test.innerclass.StaticInner$Inner //调用静态内部类方法 String info = inner.getInfo(); System.out.println(info);//HelloWorld } }
成员内部类
package com.test.innerclass; class MemberInner { private String name = "hello"; //成员内部类 class Inner { private String name = "world"; //成员内部类访问外部类的成员变量 public String getOutMemberName() { String outMemberName = MemberInner.this.name; return outMemberName; } //成员内部类访问外部类的方法 public String getOutMethod() { return MemberInner.this.getName(); } public String getInnerName() { return this.name; } } public String getName () { return name; } public Inner getInner() { return new Inner(); } } public class MemberInnerClassTest { public static void main(String[] args) { MemberInner.Inner inner = new MemberInner().new Inner(); System.out.println(inner.getOutMemberName());//hello System.out.println(inner.getOutMethod());//hello System.out.println(inner.getInnerName());//world System.out.println(new MemberInner().getInner().getClass().getName());//com.test.innerclass.MemberInner$Inner } }
方法内部类
package com.test.innerclass; class LocalInner { private String name = "cxl"; public String getName() { final String innerName = "world"; /** * 方法内部类(使用比较少) * 1.只能在方法内实例化 * 2.不能访问非final的局部变量 */ class Inner { public String getName() { return name; } public void say() { System.out.println("hello " + innerName); } } Inner inner = new Inner(); inner.say(); return inner.getName(); } } public class LocalInnerCalssTest { public static void main(String[] args) { LocalInner localInner = new LocalInner(); System.out.println(localInner.getName()); //hello world //cxl } }
匿名内部类
1.继承式的匿名内部类
父类Car
package com.test.innerclass; public class Car { public void drive() { System.out.println("Driving a car"); } }
Demo类
package com.test.innerclass; /** * 匿名内部类(没有名字的内部类) * 使用场景:只使用一次,通常用来简化代码编写(继承父类或实现接口并从重写父类或者接口中的方法) * 一个匿名内部类一定是在new的后面,用其隐含继承一个类或实现一个接口 */ public class CarDemo { public static void main(String[] args) { //最简单的一个匿名类的实例,其继承了父类Car Car carInner = new Car() { }; //输出匿名类类名 System.out.println(carInner.getClass().getName());//com.test.innerclass.CarDemo$1 //输出匿名类父类 System.out.println(carInner.getClass().getSuperclass().getName());//com.test.innerclass.Car //调用父类方法 carInner.drive();//输出结果:Driving a car //相当于下面写法 new Car() { }.drive();//输出结果:Driving a car //获取一个匿名类实例,并重写父类中的drive()方法 Car car = new Car(){ public void drive() { System.out.println("Driving In My Car"); } }; //调用自己重写的方法 car.drive();//Driving In My Car } }
2.接口式的匿名内部类
接口
package com.test.innerclass; public interface Vehicle { public void drive(); public Bus carry(Passenger passenger); }
Passenger类
package com.test.innerclass; public class Passenger { private String name; private int age; public Passenger(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Bus类
package com.test.innerclass; public class Bus { private int cost; public int getCost() { return cost; } public void setCost(int cost) { this.cost = cost; } }
Demo类
package com.test.innerclass; public class VehicleDemo { /** * @param args */ public static void main(String[] args) { //vehicle是一个父类的对象引用,其指向匿名子类的对象 Vehicle vehicle = new Vehicle() { @Override public void drive() { System.out.println("Driving In My Car"); } @Override public Bus carry(Passenger passenger) { Bus bus = new Bus(); if(passenger.getAge() < 18) { bus.setCost(1); } return bus; } }; vehicle.drive();//Driving In My Car Passenger passenger = new Passenger("小明",10); Bus bus = vehicle.carry(passenger); System.out.println(passenger.getName() + "乘公交车的费用 :" + bus.getCost() + "元");//小明乘公交车的费用 :1元 } }
3.参数式的匿名内部类
Speaker类
package com.test.innerclass; public class Speaker { public String speech(Content content,String name) { return content.sayHello(name); } }
Content接口
package com.test.innerclass; public interface Content { public String sayHello(String name); }
Demo类
package com.test.innerclass; class SpeakerDemo { public static void main(String[] args) { Speaker speaker = new Speaker(); String helloInfo = speaker.speech(new Content() { @Override public String sayHello(String name) { return "hello," + name; } }, "everyone"); System.out.println(helloInfo);//hello,everyone } }
匿名内部类应用
interface ICount { int count(); }
class Parent { int i = 0; int count() { return i++; } }
类Child,它既想继承Parent的count()方法,又想实现ICount接口中的count()方法,这个时候怎么办呢?内部类就可以大显身手了:
class Child extends Parent { ICount getCount() { return new ICount { int i = 0; int count() { return (i *= 2); } }; } }
为什么需要内部类
典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。使用内部类最吸引人的原因是:
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。