`

java内部类

    博客分类:
  • java
阅读更多

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);
        }
      };
    }
} 

 

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics