Java中的嵌套类型是指在一个类中定义另一个类,这样就可以将外部类的成员变量和方法封装起来,使其不能被外部访问。但是,由于Java语言的特性,嵌套类型无法隐藏外层类型。
首先,Java语言本身没有提供对内部类的保护机制,因此外部类中定义的内部类可以直接被外部代码所引用。例如:
public class OuterClass { public class InnerClass { // ... } public static void main(String[] args) { OuterClass.InnerClass inner = new OuterClass().new InnerClass(); } }
上面的代码中,OuterClass定义了一个内部类InnerClass,但是在main方法中却可以直接通过OuterClass.InnerClass来创建InnerClass对象。这就表明了内部类无法隐藏外层类型。
其次,Java语言本身也不允许在名字上加以区分来区分内部类与外部类。例如:
public class OuterClass { public static class InnerStaticClass { } public class InnerNonStaticClass { } public static void main(String[] args) { OuterClass.InnerStaticClass innerStatic = new OuterClass.InnerStaticClass(); OuterClass.InnerNonStaticClass innerNonStatic = new Outerclass().new InnerNonStaticclass(); } }
上面的代码中,Outerclass定义了一个静态内部类InnerStaticclass以及一个非静态内部类InnerNonstaticclass。但是在main方法中却使用相同的语法来创建这两个内部对象。这尽显出Java语言并没有提供对内部对象名字上的保护机制。
在任何类外部声明的类是顶级类。嵌套类是声明为其他类或作用域的成员的类。
有四种嵌套类:
匿名类是没有名称并同时声明的类。您可以实例化一个匿名类,在其中指定一个表达式是合法的。
一个匿名类实例只能访问局部最终变量和最终参数。
如何定义一个匿名类?
abstract class People { abstract void speak(); } public class Main { public static void main(final String[] args) { new People() { String msg = "test"; @Override void speak() { System.out.println(msg); } }.speak(); } }
上面的代码生成以下结果。
下面的代码声明和实例化一个实现接口的匿名类。
interface People { abstract void speak(); } public class Main { public static void main(final String[] args) { new People() { String msg = (args.length == 1) ? args[0] : "nothing to say"; @Override public void speak() { System.out.println(msg); } }.speak(); } }
上面的代码生成以下结果。
本地类是在声明局部变量的任何地方声明的类。局部类与局部变量具有相同的范围。
一个本地类有一个名称,可以重复使用。本地类实例可以访问周围范围的本地最终变量和最终参数。
Java局部类
class MyClass { void myMethod(final int x) { final int y = x; class LocalClass { int a = x; int b = y; } LocalClass lc = new LocalClass(); System.out.println(lc.a); System.out.println(lc.b); } } public class Main { public static void main(String[] args) { MyClass ec = new MyClass(); ec.myMethod(10); } }
上面的代码生成以下结果。
下面的代码声明了一个Iterator接口和Iter内部类。
class Item{ private String name; private String value; public Item(String n, String v){ name = n; value = v; } public String toString(){ return name + value; } } interface Iterator { boolean hasMoreElements(); Object nextElement(); } class ItemManager { private Item[] itemArray; private int index = 0; ItemManager(int size) { itemArray = new Item[size]; } Iterator iterator() { class Iter implements Iterator { int index = 0; @Override public boolean hasMoreElements() { return index < itemArray.length; } @Override public Object nextElement() { return itemArray[index++]; } } return new Iter(); } void add(Item item) { itemArray[index++] = item; } } public class Main { public static void main(String[] args) { ItemManager itemManager = new ItemManager(5); itemManager.add(new Item("#1", "A")); itemManager.add(new Item("#2", "B")); itemManager.add(new Item("#3", "C")); Iterator iter = itemManager.iterator(); while (iter.hasMoreElements()){ System.out.println(iter.nextElement()); } } }
输出:
成员类是封闭类的成员。成员类的每个实例都与封闭类的实例相关联。
成员类的实例方法可以调用实例方法封闭类和访问封闭类实例的非静态字段。
以下代码具有一个名为 EnclosingClass
的外部类和非静态成员类命名为 EnclosedClass
。
class EnclosingClass { private int outerVariable; private void privateOuterMethod() { System.out.println(outerVariable); } class EnclosedClass { void accessEnclosingClass() { outerVariable = 1; privateOuterMethod(); } } } public class Main { public static void main(String[] args) { EnclosingClass ec = new EnclosingClass(); ec.new EnclosedClass().accessEnclosingClass(); // Output: 1 } }
上面的代码生成以下结果。
下面的代码使用内部类ItemList来存储项目。
class Item { private String name; private String desc; Item(String name, String desc) { this.name = name; this.desc = desc; } String getName() { return name; } String getDesc() { return desc; } @Override public String toString() { return "Name = " + getName() + ", Desc = " + getDesc(); } } class ItemManager { private ItemList itemList; private int index = 0; ItemManager() { itemList = new ItemList(2); } boolean hasMoreElements() { return index < itemList.size(); } Item nextElement() { return itemList.get(index++); } void add(Item item) { itemList.add(item); } private class ItemList { private Item[] itemArray; private int index = 0; ItemList(int initSize) { itemArray = new Item[initSize]; } void add(Item item) { if (index >= itemArray.length) { Item[] temp = new Item[itemArray.length * 2]; for (int i = 0; i < itemArray.length; i++) temp[i] = itemArray[i]; itemArray = temp; } itemArray[index++] = item; } Item get(int i) { return itemArray[i]; } int size() { return index; } } } public class Main { public static void main(String[] args) { ItemManager itemManager = new ItemManager(); itemManager.add(new Item("1", "A")); itemManager.add(new Item("2", "B")); itemManager.add(new Item("3", "C")); while (itemManager.hasMoreElements()) System.out.println(itemManager.nextElement()); } }
上面的代码生成以下结果。
以下程序说明如何定义和使用内部类。
class Outer { int outer_x = 100; void test() { Inner inner = new Inner(); inner.display(); } class Inner { void display() { System.out.println("display: outer_x = " + outer_x); } } } public class Main { public static void main(String args[]) { Outer outer = new Outer(); outer.test(); } }
此应用程序的输出如下所示:
内部类成员只能在内部类中访问,并且可能不被外部类使用。如果您尝试编译以下代码,您将收到错误消息。
public class Main { int outer_x = 100; // this is an inner class class Inner { int y = 10; // y is local to Inner void display() { System.out.println("display: outer_x = " + outer_x); } } void showy() { System.out.println(y); } }
当编译上面的代码:
静态成员类是封闭类的静态成员。静态成员类不能访问包含类的实例字段并调用其实例方法。
静态成员可以访问包含类的静态字段并调用其静态方法,包括私有字段和方法。
下面的代码有一个静态成员类声明。
class Demo { public static void main(String[] args) { Main.EnclosedClass.accessEnclosingClass(); Main.EnclosedClass ec = new Main.EnclosedClass(); ec.accessEnclosingClass2(); } } class Main { private static int outerVariable; private static void privateStaticOuterMethod() { System.out.println(outerVariable); } static void staticOuterMethod() { EnclosedClass.accessEnclosingClass(); } static class EnclosedClass { static void accessEnclosingClass() { outerVariable = 1; privateStaticOuterMethod(); } void accessEnclosingClass2() { staticOuterMethod(); } } }
静态成员类可以声明其封闭类的多个实现。
下面的代码声明一个 Rectangle
类,它使用静态成员类为不同的数据类型提供 Rectangle
实现,一个是 double
类型另一个是 float
类型。
abstract class Rectangle { abstract double getX(); abstract double getY(); abstract double getWidth(); abstract double getHeight(); static class Double extends Rectangle { private double x, y, width, height; Double(double x, double y, double width, double height) { this.x = x; this.y = y; this.width = width; this.height = height; } double getX() { return x; } double getY() { return y; } double getWidth() { return width; } double getHeight() { return height; } } static class Float extends Rectangle { private float x, y, width, height; Float(float x, float y, float width, float height) { this.x = x; this.y = y; this.width = width; this.height = height; } double getX() { return x; } double getY() { return y; } double getWidth() { return width; } double getHeight() { return height; } } private Rectangle() { } boolean contains(double x, double y) { return (x >= getX() && x < getX() + getWidth()) && (y >= getY() && y < getY() + getHeight()); } } public class Main { public static void main(String[] args) { Rectangle r = new Rectangle.Double(10.0, 10.0, 20.0, 30.0); r = new Rectangle.Float(10.0f, 10.0f, 20.0f, 30.0f); } }
JPA教程 - JPA列精度范围示例当将Java float或double值映射到数据库表列时,我们可以设置数字类型列的精度尺度。以下代码将浮点...
JPA教程 -JPA一对一延迟加载示例以下代码显示如何使用延迟加载设置执行一对一映射。@OneToOne(fetch=LAZY)private Department de...
JPA教程 -JPA 多对多连接表示例以下代码显示如何为多对多映射设置连接表。例子下面的代码来自PersonDaoImpl.java。package cn..c...
JPA教程 -JPA查询连接多对一示例以下JPQL显示如何连接多对一映射。SELECT p FROM Professor e JOIN e.phones p)例子下面的代码来...