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);
}
};
}
}
为什么需要内部类
典型的情况是,内部类继承自某个类或实现某个接口,内部类的代码操作创建其的外围类的对象。所以你可以认为内部类提供了某种进入其外围类的窗口。使用内部类最吸引人的原因是:
每个内部类都能独立地继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。如果没有内部类提供的可以继承多个具体的或抽象的类的能力,一些设计与编程问题就很难解决。从这个角度看,内部类使得多重继承的解决方案变得完整。接口解决了部分问题,而内部类有效地实现了“多重继承”。