原文地址: http://www.geeksforgeeks.org/static-class-in-java/ Java中的静态类
http://tutorials.jenkov.com/java/nested-classes.html Java中的嵌套类
在Java中类可以是静态的么?
在Java中类可以是静态的。在Java中有静态实例变量,静态方法,以及静态块,类也可以是静态的。在Java中我们可以在类中再次定义一个类。这种类被称为嵌套类。嵌套类外围的类被称为外部类。在Java中不能使最顶层类为静态类,而只有嵌套的类可以是静态类。
静态类与非静态类的区别?
下面列出了静态类与非静态类的主要区别。非静态嵌套类通常被称为内部类。
class OuterClass{
private static String msg = "GeeksForGeeks";
private String nonStaticMsg = "nonStaticGeeksForGeeks";
// 静态嵌套类
public static class NestedStaticClass{
// 只有外部类的静态称为可以在该静态类中访问
public void printMessage(){
System.out.println("Message from nested static class: " + msg);
// 报错,因为在静态类中访问非静态成员nonStaticMsg
// System.out.println("Message from nested static class: " + nonStaticMsg);
}
}
public class InnerClass{
public void display(){
// 内部类中,静态与非静态成员都可以访问。
System.out.println("Message from nested static class: " + msg);
System.out.println("Message from nested static class: " + nonStaticMsg);
}
}
}
public class App
{
public static void main( String[] args )
{
// 创建嵌套静态类的实例
OuterClass.NestedStaticClass printer = new OuterClass.NestedStaticClass();
printer.printMessage();
// 为了创建内部类的实例,我们需要一个外部类的实例
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
// 调用内部类的非静态方法
inner.display();
// 还可以用以一步来创建内部类的实例
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
innerObject.display();
}
}
class Outer{
public static class StaticInner{
}
public class Inner{
}
public static void test(){
Inner it1 = new Inner(); // 报错,需要创建Outer,然后通过Outer建立Inner的实例
StaticInner st = new StaticInner();
}
public void test2(){
Inner it2 = new Inner();
}
}
静态嵌套类
静态嵌套类是以如下形式声明的:
public class Outer {
public static class Nested {
}
}
为了创建嵌套类的实例,你必须以外部类Outer作为类Nested的前缀来引用它。Outer.Nested instance = new Outer.Nested();由于是静态的,静态嵌套类只能通过一个其外层类的实例的引用来访问外部类实例。
非静态嵌套类(内部类)
在java中非静态嵌套类被称为内部类。内部类是与一个外部类实例相关联。必须先创建外部类实例,随后才能创建内部类。
public class Outer {
public class Inner {
}
}
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
public class Outer {
private String text = "I am private!";
public class Inner {
public void printText() {
System.out.println(text);
}
}
}
//printText中引用了一个Outer类中private成员text.这是可以的。下面是printText的调用方式。
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.printText();
如果内部类声明的域或方法与外围类有相同的名字,内部域或方法会屏蔽外部类的域或方法。
public class Outer {
private String text = "I am Outer private!";
public class Inner {
private String text = "I am Inner private";
public void printText() {
System.out.println(text);
}
}
}
上面的例子中,Outer与Inner类都包含有名为text的域。当Inner类引用text时,它引用的是自己的text域。外部类引用text时,它引用的也是自己的text域。
Java中,内部类可以引用外部类同名的text域。通过,外部类名.this.变量名 的形式来引用。
public class Outer {
private String text = "I am Outer private!";
public class Inner {
private String text = "I am Inner private";
public void printText() {
System.out.println(text);
System.out.println(Outer.this.text);
}
}
}
Java中局部类与内部类类似,局部类定义在一个方法或作用域块的内部。
class Outer {
public void printText() {
class Local {
}
Local local = new Local();
}
}
匿名类
Java中,如果嵌套类没有名称,则为匿名类。通常作为一个已经存在的类的子类来声明,或是某个接口的实现。匿名类在实例化时定义。如下定义了一个SuperClass的匿名子类。
public class SuperClass {
public void doIt() {
System.out.println("SuperClass doIt()");
}
}
SuperClass instance = new SuperClass() {
public void doIt() {
System.out.println("Anonymous class doIt()");
}
};
instance.doIt();
public interface MyInterface {
public void doIt();
}
MyInterface instance = new MyInterface() {
public void doIt() {
System.out.println("Anonymous class doIt()");
}
};
instance.doIt();
如你所见,匿名类实现了一个接口与匿名类继承另一个类十分类似。匿名类与内部类有着同样的作用域屏蔽规则。
嵌套类的好处
嵌套类的好处是,你可以将相关的类组织在一起。你可以将相关类放入一个包中,但将一个类放入另一个类内部,以加强它们之间的关联。
嵌套类通过仅仅被外围类所使用。通常嵌套类仅仅对外围类可见,仅仅是内部使用,而在对于外围类之外的类是不可见的。其它情况下,仅当外围类被使用时,嵌套类才对于外围类之外的类可见。
一个实例是,Cache类。在Cache类内部,你声明了一个CacheEntry类,这个类包含了关于Cache的信息。(信息包括:值,插入时间,访问次数等)。 如果用户不需要获取CacheEntry自身信息,Cache类的使用者是看不到CacheEntry类的,仅能看到缓存的值。然而,Cache类可能会使cacheEntry类对外部可见。这样使用者可以获得更多的信息,而不仅仅是存数的值。
如下是两个Cache的实现:
public class Cache {
private Map cacheMap = new HashMap();
private class CacheEntry {
public long timeInserted = 0;
public object value = null;
}
public void store(String key, Object value){
CacheEntry entry = new CacheEntry();
entry.value = value;
entry.timeInserted = System.currentTimeMillis();
this.cacheMap.put(key, entry);
}
public Object get(String key) {
CacheEntry entry = this.cacheMap.get(key);
if(entry == null) return null;
return entry.value;
}
}
public class Cache {
private Map cacheMap = new HashMap();
public class CacheEntry {
public long timeInserted = 0;
public object value = null;
}
public void store(String key, Object value){
CacheEntry entry = new CacheEntry();
entry.value = value;
entry.timeInserted = System.currentTimeMillis();
this.cacheMap.put(key, entry);
}
public Object get(String key) {
CacheEntry entry = this.cacheMap.get(key);
if(entry == null) return null;
return entry.value;
}
public CacheEntry getCacheEntry(String key) {
return this.cacheMap.get(key);
}
}