非静态内部类
例1.
//外部类
class Out {
private int age = 12;
//内部类
class In {
public void print() {
System.out.println(age); //非静态内部类成员可以访问外部类的private成员</span>
}
}
}
public class Demo {
public static void main(String[] args) {
Out.In in = new Out().new In();
in.print();
//或者采用下种方式访问
/*
Out out = new Out();
Out.In in = out.new In();
in.print();
*/
}
}
运行结果:12
程序编译过后会产生两个.class文件,分别是Out.class和Out$In.class
前者是外部类Out的class文件,后者是内部类In的class文件。
即成员内部类(静态内部类和非静态内部类)的class文件总是这种形式:OuterClass$InnerClass.class
创建非静态内部类对象的一般形式为: 外部类类名.内部类类名 xxx = 外部类对象名.new 内部类类名()
Out.In in = new Out().new In()可以用来生成内部类的对象,这种方法存在两个小知识点需要注意
1.开头的Out是为了标明需要生成的内部类对象在哪个外部类当中
2.必须先有外部类的对象才能生成内部类的对象,因为内部类的作用就是为了访问外部类中的成员变量
例2.
class Out {
private int age = 12;
class In {
private int age = 13;
public void print() {
int age = 14;
System.out.println("内部类方法里的局部变量:" + age);
System.out.println("内部类成员变量:" + this.age);
System.out.println("外部类成员变量:" + Out.this.age);
}
}
}
public class Demo {
public static void main(String[] args) {
Out.In in = new Out().new In();
in.print();
}
}
运行结果:
局部变量:14
内部类变量:13
外部类变量:12
非静态内部类的变量访问形式
在非静态内部类的方法内访问某个变量时,优先在该方法内查找是否存在该名字的局部变量;
若无,到该方法所在的内部类中查找是否存在该名字的成员变量;
若无,到该内部类所在的外部类中查找是否存在该名字的成员变量;
if 外部类的成员变量,内部类的成员变量,内部类方法里的局部变量同名:
访问外部类的成员变量 Out.this.属性名
访问内部类的成员变量 this.属性名
访问内部类方法里的局部变量 属性名
例3.
public class Out{
private class In{}
public static void main(String[] args){
new In(); //编译异常
}
}
运行结果:编译异常
不允许在外部类的静态成员中直接使用非静态内部类。
非静态内部类里不能有静态方法,静态成员变量,静态初始化块。
静态内部类
例4.
class Out {
private static int age = 12;
static class In {
public void print() {
System.out.println(age);
}
}
}
public class Demo {
public static void main(String[] args) {
Out.In in = new Out.In();
in.print();
}
}
运行结果:12
如果用static 将内部类静态化,那么内部类就只能访问外部类的静态成员变量,具有局限性(静态成员不能访问非静态成员)
创建静态内部类对象的一般形式为: 外部类类名.内部类类名 xxx = new 外部类类名.内部类类名()
例5.
public class Out {
static class In{
private static int a = 5;
private int b = 9;
}
public void acc(){
System.out.println(In.a);//通过类名访问静态内部类的类成员
System.out.println(new In().b);//通过实例访问静态内部类的实例成员
}
}
外部类不能直接访问静态内部类的成员
可以使用静态内部类的类名作为调用者来访问静态内部类的类成员 如 In.a
可以使用静态内部类对象作为调用者来访问静态内部类的实例成员 如 new In().b
匿名内部类
例6.
interface Product{
public double getPrice();
public String getName();
}
public class AnonymousTest {
public void test(Product p){
System.out.println("购买了一个" + p.getName() + "花掉了" + p.getPrice());
}
public static void main(String[] args){
AnonymousTest ta = new AnonymousTest();
ta.test(new Product(){
public double getPrice(){
return 567.8;
}
public String getName(){
return "AGP";
}
});
}
}
运行结果:购买了一个AGP花掉了567.8
例7.
abstract class Device{
private String name;
public abstract double getPrice();
public Device(){}
public Device(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
public class AnonymousInner {
public void test(Device d){
System.out.println("购买了" +d.getName() + "价格是" +d.getPrice());
}
public static void main(String [] args)
{
AnonymousInner ai = new AnonymousInner();
ai.test(new Device("电子示波器")
{
public double getPrice()
{
return 67.8;
}
});
Device d = new Device()
{
{
System.out.println("匿名内部类的初始化块");
}
public double getPrice()
{
return 56.2;
}
public String getName()
{
return "键盘";
}
};
ai.test(d);
}
}
运行结果:
购买了电子示波器价格是67.8
匿名内部类的初始化块
购买了键盘价格是56.2
匿名内部类必须继承一个父类或实现一个接口,但最多只能两者选其一
定义匿名内部类的格式如下:
new 实现接口(){
}
或
new 父类构造器(实参){
}
例8.
interface A{
void test();
}
public class ATest {
public static void main(String[] args){
int age = 8;
A a = new A(){
public void test(){
System.out.println(age);//从java8开始,匿名内部类,局部内部类允许访问非final的局部变量
}
};
a.test();
}
}
运行结果:8(java8下,8之前会出现编译错误)
<span style="font-size:14px;">从java8开始,匿名内部类,局部内部类允许访问非final的局部变量</span>
参考资料http://www.cnblogs.com/nerxious/archive/2013/01/24/2875649.html
疯狂Java讲义