萨满大地之盾没有了7.0:Java 类之间的调用a

来源:百度文库 编辑:九乡新闻网 时间:2024/05/17 04:01:47
需要了解2个概念:内部类和静态修饰符static
1)首先,用内部类是因为内部类与所在外部类有一定的关系,往往只有该外部类调用此内部类。所以没有必要专门用一个Java文件存放这个类。
2)静态都是用来修饰类的内部成员的。比如静态方法,静态成员变量,静态常量。它唯一的作用就是随着类的加载(而不是随着对象的产生)而产生,以致可以用类名+静态成员名直接获得。
这样静态内部类就可以理解了,因为这个类没有必要单独存放一个文件,它一般来说只被所在外部类使用。并且它可以直接被用 外部类名+内部类名 获得。

以下举例说明怎么使用:
Student类有个叫School的内部类(非静态)
Student stu = new Student();
stu.School sch = new stu.School();
sch就是School的一个对象。

假如School是内部静态类:
Student.School sch = new Student.School();
外创建内部类就是把类定义至于外围类的里面



静态方法在JVM刚加载的时候就编译过了...在程序的运行过程中随时可以调用...不需要去实例化某个对象然后再去调用...可以直接用类名去调用...不过你想一下,在JVM刚加载的进修就编译过了..也就是说它一直存在着...也就是说它一直占用这内存中的地址空间...所以说也是比较占资源的噢!

   相对于静态方法而言,动态方法占的内存资源就少些...因为它是什么时候使用什么时候实例化...也就是说在不使用的时候它是不会占用资源的...相对与静态方法的缺点是它每次使用的时候都要进行实例化...也就是说比较麻烦一些了...
Java代码
  1. public class Parcel1 {   
  2.     class Destination {   
  3.         private String label;   
  4.   
  5.         Destination(String whereTo) {   
  6.             label = whereTo;   
  7.         }   
  8.   
  9.         String readLabel() {   
  10.             return label;   
  11.         }   
  12.     }   
  13.   
  14.     //在类的的函数中使用内部类,与使用普通类没多大区别   
  15.     public void ship(String dest) {   
  16.         Destination d = new Destination(dest);   
  17.         System.out.println(d.readLabel());   
  18.     }   
  19.   
  20.     public static void main(String[] args) {   
  21.         Parcel1 p = new Parcel1();   
  22.         p.ship("Tasmania");   
  23.     }   
  24. }  
public class Parcel1 {class Destination {private String label;Destination(String whereTo) {label = whereTo;}String readLabel() {return label;}}//在类的的函数中使用内部类,与使用普通类没多大区别public void ship(String dest) {Destination d = new Destination(dest);System.out.println(d.readLabel());}public static void main(String[] args) {Parcel1 p = new Parcel1();p.ship("Tasmania");}}

如果想从外部类的非静态方法之外的任意位置创建某个内部类的对象,必须具体地知名这个对象饿类型(OuterClassName.InnerClassName),比如
Java代码
  1. public class Parcel2 {   
  2.     class Contents {   
  3.         private int i = 11;   
  4.   
  5.         public int value() {   
  6.             return i;   
  7.         }   
  8.     }   
  9.   
  10.     public Contents contents() {   
  11.         return new Contents();   
  12.     }   
  13.   
  14.     public void ship(String dest) {   
  15.         Contents c = contents();   
  16.         Destination d = to(dest);   
  17.         System.out.println(d.readLabel());   
  18.     }   
  19.   
  20.     public static void main(String[] args) {   
  21.         Parcel2 p = new Parcel2();   
  22.         p.ship("Tasmania");   
  23.         Parcel2 q = new Parcel2();   
  24.         // Defining references to inner classes:   
  25.         Parcel2.Contents c = q.contents();   
  26.     }   
  27. }  
public class Parcel2 {class Contents {private int i = 11;public int value() {return i;}}public Contents contents() {return new Contents();}public void ship(String dest) {Contents c = contents();Destination d = to(dest);System.out.println(d.readLabel());}public static void main(String[] args) {Parcel2 p = new Parcel2();p.ship("Tasmania");Parcel2 q = new Parcel2();// Defining references to inner classes:Parcel2.Contents c = q.contents();}}

外部类拥有其外围类的所有元素的访问权
如果你需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this,如下:
Java代码
  1. public class DotThis {   
  2.     void f() {   
  3.         System.out.println("DotThis.f()");   
  4.     }   
  5.   
  6.     public class Inner {   
  7.         public DotThis outer() {   
  8.             //通过外部类名字后面紧跟远点和this获取外部类对象         //的引用   
  9.             return DotThis.this;   
  10.         }   
  11.     }   
  12.   
  13.     public Inner inner() {   
  14.         return new Inner();   
  15.     }   
  16.   
  17.     public static void main(String[] args) {   
  18.         DotThis dt = new DotThis();   
  19.         DotThis.Inner dti = dt.inner();   
  20.         //通过获取到的外部类调用外部类中的方法   
  21.         dti.outer().f();   
  22.     }   
  23. }  
public class DotThis {void f() {System.out.println("DotThis.f()");}public class Inner {public DotThis outer() {//通过外部类名字后面紧跟远点和this获取外部类对象//的引用return DotThis.this;}}public Inner inner() {return new Inner();}public static void main(String[] args) {DotThis dt = new DotThis();DotThis.Inner dti = dt.inner();//通过获取到的外部类调用外部类中的方法dti.outer().f();}}

如果你要在main函数中创建一个内部类对象,你必须在new表达式中提供对其他外部类对象的引用,这是需要使用.new语法,比如上例代码在main中修改创建内部类Inner对象的方法改为DotThis.Inner dti = dt.new Inner()后效果一样
在拥有外部类对象之前是不可能创建内部类对象,因为内部类对象会暗暗地连接到创建它的外部类对象上,但是如果你创建的是嵌套类(静态内部类),就不需要对外部类对象的引用

在方法的作用域内(而不是在其他类的作用域内)创建一个完整的类.这被称作局部内部类:
Java代码
  1. public interface Destination {   
  2.   String readLabel();   
  3. }  
public interface Destination {String readLabel();}

Java代码
  1. public class Parcel5 {   
  2.     public Destination destination(String s) {   
  3.         class PDestination implements Destination {   
  4.             private String label;   
  5.   
  6.             private PDestination(String whereTo) {   
  7.                 label = whereTo;   
  8.             }   
  9.   
  10.             public String readLabel() {   
  11.                 return label;   
  12.             }   
  13.         }   
  14.         return new PDestination(s);   
  15.     }   
  16.   
  17.     public static void main(String[] args) {   
  18.         Parcel5 p = new Parcel5();   
  19.         Destination d = p.destination("Tasmania");   
  20.     }   
  21. }  
public class Parcel5 {public Destination destination(String s) {class PDestination implements Destination {private String label;private PDestination(String whereTo) {label = whereTo;}public String readLabel() {return label;}}return new PDestination(s);}public static void main(String[] args) {Parcel5 p = new Parcel5();Destination d = p.destination("Tasmania");}}

PDestination类是destination()方法的一部分,所以在destination()之外不能访问,在return语句中的向上转型,返回的是Destination的引用,是一个基类
你也可以再同一个子目录下的任意类中对某个内部类使用类标示符PDestination,因为定义在方法内部,所以不会出现命名冲突.

在任意的作用域内嵌入一个内部类,比如在if语句的作用域内:
Java代码
  1. public class Parcel6 {   
  2.     private void internalTracking(boolean b) {   
  3.         if (b) {   
  4.             class TrackingSlip {   
  5.                 private String id;   
  6.                 TrackingSlip(String s) {   
  7.                     id = s;   
  8.                 }   
  9.                 String getSlip() {   
  10.                     return id;   
  11.                 }   
  12.             }   
  13.             TrackingSlip ts = new TrackingSlip("slip");   
  14.             String s = ts.getSlip();   
  15.         }   
  16.     }   
  17.     public void track() {   
  18.         internalTracking(true);   
  19.     }   
  20.     public static void main(String[] args) {   
  21.         Parcel6 p = new Parcel6();   
  22.         p.track();   
  23.     }   
  24. }  
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("slip");String s = ts.getSlip();}}public void track() {internalTracking(true);}public static void main(String[] args) {Parcel6 p = new Parcel6();p.track();}}

这并不是说该类的创建时有条件的,它其实与别的类一起编译过了,然而,在定义TrackingSlip的作用域之外,它是不可用的,除此之外,与普通的类一样

匿名内部类,一直看起来有点奇怪
Java代码
  1. public interface Contents {   
  2.   int value();   
  3. }  
public interface Contents {int value();}
Java代码
  1. public class Parcel7 {   
  2.     public Contents contents() {   
  3.         return new Contents() {   
  4.             private int i = 11;   
  5.             public int value() {   
  6.                 return i;   
  7.             }   
  8.         };     
  9.     }   
  10.     public static void main(String[] args) {   
  11.         Parcel7 p = new Parcel7();   
  12.         Contents c = p.contents();   
  13.         System.out.println(c.value());   
  14.     }   
  15. }  
public class Parcel7 {public Contents contents() {return new Contents() {private int i = 11;public int value() {return i;}};}public static void main(String[] args) {Parcel7 p = new Parcel7();Contents c = p.contents();System.out.println(c.value());}}

将返回值的生成与表示这个返回值的类的定义结合在一起,另外这个类是匿名的, 它没有名字.其实匿名类是非匿名类,然后去实现一个接口的简化形式

如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么编译器会要求其参数引用时final的
Java代码
  1. public interface Destination {   
  2.   String readLabel();   
  3. }  
public interface Destination {String readLabel();}

Java代码
  1. public class Parcel9 {   
  2.     //参数dest必须定义成final的,才能在匿名内部类中使用   
  3.     public Destination destination(final String dest) {   
  4.         return new Destination() {   
  5.             private String label = dest;   
  6.             public String readLabel() {   
  7.                 return label;   
  8.             }   
  9.         };   
  10.     }   
  11.     public static void main(String[] args) {   
  12.         Parcel9 p = new Parcel9();   
  13.         Destination d = p.destination("Tasmania");   
  14.         System.out.println(d.readLabel());   
  15.     }   
  16. }  
public class Parcel9 {//参数dest必须定义成final的,才能在匿名内部类中使用public Destination destination(final String dest) {return new Destination() {private String label = dest;public String readLabel() {return label;}};}public static void main(String[] args) {Parcel9 p = new Parcel9();Destination d = p.destination("Tasmania");System.out.println(d.readLabel());}}


匿名内部类不可能有命名构造器(因为它根本没名字),但通过实例初始化,能够达到为匿名内部类创建一个构造器的效果
Java代码
  1. abstract class Base {   
  2.     public Base(int i) {   
  3.         System.out.print("Base constructor, i = " + i);   
  4.     }   
  5.     public abstract void f();   
  6. }   
  7. public class AnonymousConstructor {   
  8.     //这里i不用声明为final,因为不会再匿名内部类被直接使用   
  9.     public static Base getBase(int i) {   
  10.         return new Base(i) {   
  11.             {   
  12.                 System.out.print("Inside instance initializer");   
  13.             }   
  14.             public void f() {   
  15.                 System.out.print("In anonymous f()");   
  16.             }   
  17.         };   
  18.     }   
  19.     public static void main(String[] args) {   
  20.         Base base = getBase(47);   
  21.         base.f();   
  22.     }   
  23. }  
abstract class Base {public Base(int i) {System.out.print("Base constructor, i = " + i);}public abstract void f();}public class AnonymousConstructor {//这里i不用声明为final,因为不会再匿名内部类被直接使用public static Base getBase(int i) {return new Base(i) {{System.out.print("Inside instance initializer");}public void f() {System.out.print("In anonymous f()");}};}public static void main(String[] args) {Base base = getBase(47);base.f();}}


下面来看一段代码
Java代码
  1. public class Parcel10 {   
  2.     public Destination destination(final String dest, final float price) {   
  3.         return new Destination() {   
  4.             private int cost;   
  5.             // 这里的if语句不能作为字段初始化的一部分来执行   
  6.             {   
  7.                 cost = Math.round(price);   
  8.                 if (cost > 100)   
  9.                     System.out.println("Over budget!");   
  10.             }   
  11.             private String label = dest;   
  12.   
  13.             public String readLabel() {   
  14.                 return label;   
  15.             }   
  16.         };   
  17.     }   
  18.   
  19.     public static void main(String[] args) {   
  20.         Parcel10 p = new Parcel10();   
  21.         Destination d = p.destination("Tasmania", 101.395F);   
  22.     }   
  23. }  
public class Parcel10 {public Destination destination(final String dest, final float price) {return new Destination() {private int cost;// 这里的if语句不能作为字段初始化的一部分来执行{cost = Math.round(price);if (cost > 100)System.out.println("Over budget!");}private String label = dest;public String readLabel() {return label;}};}public static void main(String[] args) {Parcel10 p = new Parcel10();Destination d = p.destination("Tasmania", 101.395F);}}

对于匿名类而言,实例初始化的实际效果就是构造器,当然它受到了限制-----不能重载实例化方法,所以你仅有一个这样的构造器
匿名内部类与正规的继承相比有些受限,因为匿名内部类既可以扩展类,也可以实现接口,但是不能两者兼备.而且如果是实现接口,也只能实现一个接口

利用匿名内部类,定义工厂方法
Java代码
  1. interface Service {   
  2.     void method1();   
  3.   
  4.     void method2();   
  5. }   
  6.   
  7. interface ServiceFactory {   
  8.     Service getService();   
  9. }   
  10.   
  11. class Implementation1 implements Service {   
  12.     private Implementation1() {   
  13.     }   
  14.   
  15.     public void method1() {   
  16.         System.out.println("Implementation1 method1");   
  17.     }   
  18.   
  19.     public void method2() {   
  20.         System.out.println("Implementation1 method2");   
  21.     }   
  22.   
  23.     public static ServiceFactory factory = new ServiceFactory() {   
  24.         public Service getService() {   
  25.             return new Implementation1();   
  26.         }   
  27.     };   
  28. }   
  29.   
  30. class Implementation2 implements Service {   
  31.     private Implementation2() {   
  32.     }   
  33.   
  34.     public void method1() {   
  35.         System.out.println("Implementation2 method1");   
  36.     }   
  37.   
  38.     public void method2() {   
  39.         System.out.println("Implementation2 method2");   
  40.     }   
  41.     //利用匿名内部类的方式实现一个接口,实现工厂的方式得到当前类   
  42.     public static ServiceFactory factory = new ServiceFactory() {   
  43.         public Service getService() {   
  44.             return new Implementation2();   
  45.         }   
  46.     };   
  47. }   
  48.   
  49. public class Factories {   
  50.     public static void serviceConsumer(ServiceFactory fact) {   
  51.         Service s = fact.getService();   
  52.         s.method1();   
  53.         s.method2();   
  54.     }   
  55.   
  56.     public static void main(String[] args) {   
  57.         serviceConsumer(Implementation1.factory);   
  58.         serviceConsumer(Implementation2.factory);   
  59.     }   
  60. }  
interface Service {void method1();void method2();}interface ServiceFactory {Service getService();}class Implementation1 implements Service {private Implementation1() {}public void method1() {System.out.println("Implementation1 method1");}public void method2() {System.out.println("Implementation1 method2");}public static ServiceFactory factory = new ServiceFactory() {public Service getService() {return new Implementation1();}};}class Implementation2 implements Service {private Implementation2() {}public void method1() {System.out.println("Implementation2 method1");}public void method2() {System.out.println("Implementation2 method2");}//利用匿名内部类的方式实现一个接口,实现工厂的方式得到当前类public static ServiceFactory factory = new ServiceFactory() {public Service getService() {return new Implementation2();}};}public class Factories {public static void serviceConsumer(ServiceFactory fact) {Service s = fact.getService();s.method1();s.method2();}public static void main(String[] args) {serviceConsumer(Implementation1.factory);serviceConsumer(Implementation2.factory);}}


建议:优先实用类而不是接口,如果你的设计中需要某个接口,你必须了解它,否则.不到迫不得已,不要将其放到你的设计中

如果不需要内部类对象与其外围类对象之间有联系,那么可以讲内部类声明为static.通常称为嵌套类,当内部类是static时,意味着:

    [1]要创建嵌套类的对象,并不需要其外围类的对象
    [2]不能从嵌套类的对象中访问非静态的外围类对象

嵌套类与普通的内部类还有一个区别:普通内部类的字段的字段与方法,只能放在类的外部层次上,所以普通的内部类不能有static数据和static字段,也不能包含嵌套类.但是在嵌套类里可以包含所有这些东西
Java代码
  1. public class Parcel11 {   
  2.     private static class ParcelContents implements Contents {   
  3.         private int i = 11;   
  4.         public int value() {   
  5.             return i;   
  6.         }   
  7.     }   
  8.     protected static class ParcelDestination implements Destination {   
  9.         private String label;   
  10.         private ParcelDestination(String whereTo) {   
  11.             label = whereTo;   
  12.         }   
  13.         public String readLabel() {   
  14.             return label;   
  15.         }   
  16.         // 嵌套类可以包括其他静态元素   
  17.         public static void f() {   
  18.         }   
  19.         static int x = 10;   
  20.         static class AnotherLevel {   
  21.             public static void f() {   
  22.             }   
  23.             static int x = 10;   
  24.         }   
  25.     }   
  26.     public static Destination destination(String s) {   
  27.         return new ParcelDestination(s);   
  28.     }   
  29.     public static Contents contents() {   
  30.         return new ParcelContents();   
  31.     }   
  32.     public static void main(String[] args) {   
  33.         Contents c = contents();   
  34.         Destination d = destination("Tasmania");   
  35.     }   
  36. }  
public class Parcel11 {    private static class ParcelContents implements Contents {    private int i = 11;    public int value() {    return i;    }    }    protected static class ParcelDestination implements Destination {    private String label;    private ParcelDestination(String whereTo) {    label = whereTo;    }    public String readLabel() {    return label;    }    // 嵌套类可以包括其他静态元素    public static void f() {    }    static int x = 10;    static class AnotherLevel {    public static void f() {    }    static int x = 10;    }    }    public static Destination destination(String s) {    return new ParcelDestination(s);    }    public static Contents contents() {    return new ParcelContents();    }    public static void main(String[] args) {    Contents c = contents();    Destination d = destination("Tasmania");    }    }


正常情况下,不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分,你放到接口中的任何类都自动的是public和static.因为类是static,只是将嵌套类至于接口的命名空间内.你甚至可以再内部类中实现其外围接口
Java代码
  1. public interface ClassInInterface {   
  2.     void howdy();   
  3.   
  4.     class Test implements ClassInInterface {   
  5.         public void howdy() {   
  6.             System.out.println("Howdy!");   
  7.         }   
  8.   
  9.         public static void main(String[] args) {   
  10.             new Test().howdy();   
  11.         }   
  12.     }   
  13. }  
public interface ClassInInterface {    void howdy();    class Test implements ClassInInterface {    public void howdy() {    System.out.println("Howdy!");    }    public static void main(String[] args) {    new Test().howdy();    }    }    }


以前一直不知道,嵌套类竟然可以这样用
Java代码
  1. public class TestBed {   
  2.   public void f() { System.out.println("f()"); }   
  3.   public static class Tester {   
  4.     public static void main(String[] args) {   
  5.       TestBed t = new TestBed();   
  6.       t.f();   
  7.     }   
  8.   }   
  9. }  
public class TestBed {    public void f() { System.out.println("f()"); }    public static class Tester {    public static void main(String[] args) {    TestBed t = new TestBed();    t.f();    }    }    }

就是可以把main方法放在嵌套类中

一个内部类被嵌套多少层不重要,它能透明地访问所有它所嵌入的外围类的所有成员,如下
Java代码
  1. class MNA {   
  2.     private void f() {   
  3.     }   
  4.     class A {   
  5.         private void g() {   
  6.         }   
  7.         public class B {   
  8.             void h() {   
  9.                 //访问A对象的g方法   
  10.                 g();   
  11.                 //访问MNA对象的f方法   
  12.                 f();   
  13.             }   
  14.         }   
  15.     }   
  16. }   
  17.   
  18. public class MultiNestingAccess {   
  19.     public static void main(String[] args) {   
  20.         MNA mna = new MNA();   
  21.         MNA.A mnaa = mna.new A();   
  22.         MNA.A.B mnaab = mnaa.new B();   
  23.         mnaab.h();   
  24.     }   
  25. }