为什么要使用内部类:
使用内部类最吸引人的原因是,每个内部类都能独立的继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响
1 内部类可以拥有多个实例,每个实例都有自己的状态信息,并且与其他外围对象的信息相互独立
2 在单个外围类中,可以让多个内部类以不同的方式实现同一个接口,or继承同一个类。
3 创建内部类对象的时刻并不依赖于外围类对象的创建
4内部类并没有令人迷惑的 is-a关系,他就是一个独立的实体
5内部类提供了更好的封装,除了该外围类,其他类都不能访问
内部类基础
将一个类定义在另一个类里面or方法里面。就是内部类
public class OuterClass {
private String name ;
private int age;
/**省略getter和setter方法**/
public class InnerClass{
public InnerClass(){
name = "chenssy";
age = 23;
}
public void display(){
System.out.println("name:" + getName() +" ;age:" + getAge());
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.display();
}
}
--------------
Output:
name:chenssy ;age:23
看如何创建内部类,
同时如果我们需要生成对外部类对象的引用,可以使用OuterClassName.this,这样就能够产生一个正确引用外部类的引用了。当然这点实在编译期就知晓了,没有任何运行时的成本
public class OuterClass {
public void display(){
System.out.println("OuterClass...");
}
public class InnerClass{
public OuterClass getOuterClass(){
return OuterClass.this;
}
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
OuterClass.InnerClass innerClass = outerClass.new InnerClass();
innerClass.getOuterClass().display();
}
}
-------------
Output:
OuterClass...
内部类是一个编译时的概念,一旦编译成功后,它就与外围类属于两个完全不听的类,他们之间有一些联系,对于一个名为OuterClass的外围类和一个名为InnerClass的内部类,在编译成功后,会出现两个class文件,
OuterClass.class和OuterClass$InnerClass.class
分为:
成员内部类
局部内部类
匿名内部类
静态内部类
成员内部类:
成员内部类可以无条件的访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
class Circle {
private double radius = 0;
public static int count =1;
public Circle(double radius) {
this.radius = radius;
}
class Draw { //内部类
public void drawSahpe() {
System.out.println(radius); //外部类的private成员
System.out.println(count); //外部类的静态成员
}
}
}
当成员内类拥有和外部类同名的成员变量or方法时,会发生隐藏现象,默认访问的是成员内部类的成员。如果要访问外部同名成员,需要按照如下方式进行访问:
外部类.this.成员变量
外部类.this.成员方法
内部类可以无条件的访问外部类的成员,而外部类想访问内部类的成员却不可以随心所欲访问了,外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,在通过指向这个对象的引用来访问:
class Circle {
private double radius = 0;
public Circle(double radius) {
this.radius = radius;
getDrawInstance().drawSahpe(); //必须先创建成员内部类的对象,再进行访问
}
private Draw getDrawInstance() {
return new Draw();
}
class Draw { //内部类
public void drawSahpe() {
System.out.println(radius); //外部类的private成员
}
}
}
内部类特殊的语法规则:
成员内部类是依附外部类存在的,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象,因为内部类的作用是为了访问外部类的成员变量:
内部类中声明的所有静态域必须是final,每一个静态域只有一个实例,不过对于每个外部对象,分别会有一个单独的内部类实例。如果这个域不是final,它可能不是唯一的
内部类不能有static方法。
public class Test {
public static void main(String[] args) {
//第一种方式:
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner(); //必须通过Outter对象来创建
//第二种方式:
Outter.Inner inner1 = outter.getInnerInstance();
}
}
class Outter {
private Inner inner = null;
public Outter() {
}
public Inner getInnerInstance() {
if(inner == null)
inner = new Inner();
return inner;
}
class Inner {
public Inner() {
}
}
}
内部类和累的成员一样,可以拥有多种权限修饰,可以拥有private,protected,public访问权限以及包访问权限。
局部内部类:
定义在一个方法or一个作用域里面的类,和成员内部类的区别在于局部内部类的访问权限仅在于方法内or作用域内
class People{
public People() {
}
}
class Man{
public Man(){
}
public People getWoman(){
class Woman extends People{ //局部内部类
int age =0;
}
return new Woman();
}
}
局部内部类和局部变量一样,不能有public,protected,private以及static修饰符等
public class Parcel5 {
public Destionation destionation(String str){
class PDestionation implements Destionation{
private String label;
private PDestionation(String whereTo){
label = whereTo;
}
public String readLabel(){
return label;
}
}
return new PDestionation(str);
}
public static void main(String[] args) {
Parcel5 parcel5 = new Parcel5();
Destionation d = parcel5.destionation("chenssy");
}
}
public class Parcel6 {
private void internalTracking(boolean b){
if(b){
class TrackingSlip{
private String id;
TrackingSlip(String s) {
id = s;
}
String getSlip(){
return id;
}
}
TrackingSlip ts = new TrackingSlip("chenssy");
String string = ts.getSlip();
}
}
public void track(){
internalTracking(true);
}
public static void main(String[] args) {
Parcel6 parcel6 = new Parcel6();
parcel6.track();
}
}
匿名内部类:
唯一一种没有构造器的类,所以使用方位非常有限,一版用于只是对继承方法的实现or重写
scan_bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
history_bt.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
等同于
private void setListener()
{
scan_bt.setOnClickListener(new Listener1());
history_bt.setOnClickListener(new Listener2());
}
class Listener1 implements View.OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
class Listener2 implements View.OnClickListener{
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
}
静态内部类;
也是定义在另一个类里面的类,只不过在类前面多了static关键字修饰,静态内部类是不依赖与外部类的
这就意味着:
1 和类的静态成员属性类似,不能使用外部类的非static成员变量or方法。
2 在没有外部类的对象情况下,可以创建静态内部类的对象,
public class OuterClass {
private String sex;
public static String name = "chenssy";
/**
*静态内部类
*/
static class InnerClass1{
/* 在静态内部类中可以存在静态成员 */
public static String _name1 = "chenssy_static";
public void display(){
/*
* 静态内部类只能访问外围类的静态成员变量和方法
* 不能访问外围类的非静态成员变量和方法
*/
System.out.println("OutClass name :" + name);
}
}
/**
* 非静态内部类
*/
class InnerClass2{
/* 非静态内部类中不能存在静态成员 */
public String _name2 = "chenssy_inner";
/* 非静态内部类中可以调用外围类的任何成员,不管是静态的还是非静态的 */
public void display(){
System.out.println("OuterClass name:" + name);
}
}
/**
* @desc 外围类方法
* @author chenssy
* @data 2013-10-25
* @return void
*/
public void display(){
/* 外围类访问静态内部类:内部类. */
System.out.println(InnerClass1._name1);
/* 静态内部类 可以直接创建实例不需要依赖于外围类 */
new InnerClass1().display();
/* 非静态内部的创建需要依赖于外围类 */
OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();
/* 方位非静态内部类的成员需要使用非静态内部类的实例 */
System.out.println(inner2._name2);
inner2.display();
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.display();
}
}
----------------
Output:
chenssy_static
OutClass name :chenssy
chenssy_inner
OuterClass name:chenssy
深入理解内部类
成员内部类编译过后添加了一个指向外部类对象的引用所以可以访问外部类成员变量
静态内部类是不持有指向外部对象的引用
内部类的使用场景和好处
内部类是Java完善多继承机制
public class Father {
public int strong(){
return 9;
}
}
public class Mother {
public int kind(){
return 8;
}
}
public class Son {
/**
* 内部类继承Father类
*/
class Father_1 extends Father{
public int strong(){
return super.strong() + 1;
}
}
class Mother_1 extends Mother{
public int kind(){
return super.kind() - 2;
}
}
public int getStrong(){
return new Father_1().strong();
}
public int getKind(){
return new Mother_1().kind();
}
}
public class Test1 {
public static void main(String[] args) {
Son son = new Son();
System.out.println("Son 的Strong:" + son.getStrong());
System.out.println("Son 的kind:" + son.getKind());
}
}
----------------------------------------
Output:
Son 的Strong:10
Son 的kind:6
儿子继承了父亲,变得比父亲更加强壮,同时也继承了母亲,变得比母亲更加温柔,定义了两个内部类,分别继承Father,Mother,且都可以自然的获取父类的行为,这是内部类一个重要的特点。
内部类可以继承一个与外部类无关的类,保证了内部类的独立性。