内部类的对象总有一个隐式引用,指向创建它的外部类对象:
// 我们假设将外围类对象的引用称为outer(实际上是隐式的)
public class A { // OuterClass
private boolean yes;
... // fields
// 当在start里面构造一个内部类B对象时,
// 编译器就会将外部类A的this引用传入内部类B的构造器
public void start() { ...}
public class B { // InnerClass
... // fields
// (隐式)自动在内部类生成一个构造器来设置outer
public B(A xxx) {
outer = xxx;
}
public void abc() { // 然后调用外部类的字段
if (outer.yes) ...;
}
}
}
interface Selector {
boolean end();
Object current_ele();
void next();
}
public class Sequence {
// 初始化数组:
private Object[] items;
// 初始化索引
private int index = 0;
// 初始化数组长度
public Sequence(int size) { items = new Object[size];}
// 迭代按索引顺序给数组赋值
public void add(Object x) { if (index < items.length) items[index++] = x;}
private class SequenceSelector implements Selector {
private int i = 0;
public boolean end() { return i == items.length;}
public Object current_ele() { return items[i];}
public void next() { if (i < items.length) i++;}
}
// 返回一个内部类对象, 核心语句,将内部类外围类链接起来
public Selector selector() { return new SequenceSelector();}
public static void main(String[] args) {
// 构建数组
Sequence sequence = new Sequence(10);
for (int i = 10; i > 0; i--) sequence.add(Integer.toString(i));
// 构建迭代器
Selector selector = sequence.selector();
while (!selector.end()) {
print(selector.current_ele() + " ");
selector.next(); // 移到下个元素
}
}
}
在外围类的作用域外,可以这样引用内部类:OuterClass.InnerClass
public class Parcel2 {
static class Contents {
private int i = 11;
public int value() { return i;}
}
static class Destination {
private String label;
Destination(String whereTo) { label = whereTo;}
String readLabel() { return label;}
}
public Destination to(String s) {
return new Destination(s);
}
public Contents contents() {
return new Contents();
}
public void ship(String dest) {
Contents c = contents();
Destination d = to(dest);
println(d.readLabel() + c.value());
}
public static void main(String[] args) {
Parcel2 p = new Parcel2();
p.ship("Tasmania");
Parcel2 q = new Parcel2();
// 定义一个引用指向内部类
Parcel2.Contents c = q.contents();
Parcel2.Destination d = q.to("Borneo");
}
}
可以在内部类这样引用外部类:
public class Test {
void f() { println("Test.f()");}
public class Inner {
public Test giveOuter() {
return Test.this; // 指向外部类
}
}
public Inner giveInner() { return new Inner();}
public static void main(String[] args) {
Test t = new Test();
Test.Inner i = t.giveInner();
i.giveOuter().f();
}
}
让其他对象创建内部类:
outerObject.new InnerClass(constructor parameters);
public class Test {
class Contents {
private int i = 11;
public int value() { return i;}
}
class Destination {
private String label;
Destination(String whereTo) { label = whereTo;}
String readLabel() { return label;}
}
}
class Outsider { // 独立的类
public static void main(String[] args) {
Test t = new Test();
Test.Contents c = t.new Contents(); // 引用内部类
Test.Destination d = t.new Destination("Despicable ");
println(d.readLabel());
}
}
我们假设在包A创建一个接口;包B创建一个包含protected内部类Inner的外围类Outer,Inner实现包A接口;在包C设计一个类继承包B的Outer,然后提供一个方法返回转型为包A接口的Inner对象。要注意的是,Inner会自动生成一个无参构造器,访问级别和Inner一样是protected,而在包C继承了包B的Outer时候,你在不同包且又不是Inner子类,在protected限制下就无法new Inner();所以要手动在Inner构造一个public Inner();
如果指示创建这个类的一个对象,甚至不需要为类指定名字,这种语法是指:创建一个继承自Contents的匿名类的对象
public class Parcel7 {
public Contents contents() {
return new Contents() { // 插入类的定义
private int i = 11;
@Override
public int value() { return i;}
}; // 结束
}
}
当你的基类需要一个有参数的构造器:
class Wrapping {
private int i;
// 有参构造器
public Wrapping(int x) { i = x;}
public int value() { return i;}
}
public class Parcel8 {
public Wrapping wrapping(int x) { // 在这里Wrapping类似于“接口”
return new Wrapping(x) { // 定义继承于普通类Wrapping的子类
public int value() { return super.value() * 47;}
};
}
public static void main(String[] args) {
Parcel8 p = new Parcel8();
Wrapping w = p.wrapping(10);
println(w.value()); ///: 470
}
}
匿名内部类如果要引用外部类定义的对象,则其参数引用要final;即外部类定义的方法参数如果直接给内部类用的话则必须final,即事实最终变量
public class Parcel9 {
public Destination destination(final String dest) {
return new Destination() {
private String label = dest;
@Override
public String readLabel() { return label;}
};
}
}
实例初始化,达到匿名类内部实现构造器效果:
abstract class Base {
public Base(int i) { println("Base constructor: " + i);}
public abstract void f();
}
public class Parcel10 { // 参数传给构造器而不是匿名内部类
public static Base getBase(int i) {
return new Base(i) { // 实例初始化
{ println("Inside the instance initializer");}
@Override
public void f() { println("In anonymous f()");}
};
}
}
实例初始化块:
class Skeleton {
public Skeleton(int value, String description) { }
}
public class Parcel11 {
public Skeleton ske(int value, String description) {
return new Skeleton(value, description) {
private int cost;
{ // 无法重载,所以匿名内部类只有一个“构造器”,
// 即所谓的实例初始化块
cost = Math.round(value);
if (cost > 100) println(description);
}
};
}
public static void main(String[] args) {
Parcel11 p = new Parcel11();
Skeleton ske = p.ske(120, "fucking cheap!");
}
}
工厂方法是实现代码和接口完全分离的方法之一(即解耦),生成遵循某个接口的对象的典型方法。与直接调用构造器不同,在工厂对象上调用的是创建方法,该工厂对象将生成接口的某个实现的对象。使用工厂方法,避免指定创建Service确切类型。
interface Service { // 接口1
void method1();
void method2();
}
interface ServiceFactory { // 接口2
Service getService();
}
class Implementation implements Service {
private Implementation() {} // 构造器
public void method1() { println("called Implementation method1");}
public void method2() { println("called Implementation method2");}
public static ServiceFactory factory = // Implementation::new
new ServiceFactory() { // 匿名内部工厂类,即实现了接口2
@Override
public Service getService() { // 生成Service对象
return new Implementation();
}
};
}
public class FactoryDP {
public static void serviceConsumer(ServiceFactory sf) {
Service s = sf.getService();
s.method1();
s.method2();
}
public static void main(String[] args) {
serviceConsumer(Implementation.factory);
}
}
静态内部类类似于其他内部类,只不过它的对象没有生成它的外围类对象的引用,所以不能从嵌套类的对象中访问非静态的外围类对象;而普通内部类不能有static数据和字段,嵌套类可以有。而且嵌套类不能有.this链接外围类对象。
public class StaticInnerClassTest {
public static void main(String[] args) {
var values = new double[20];
// fill the array.
for (int i = 0; i < values.length; i++) {
values[i] = 100 * Math.random();
}
// call the static inner class
ArrayAlg.Pair p = ArrayAlg.minmax(values);
println("min = " + p.getFirst());
println("max = " + p.getSecond());
}
}
class ArrayAlg {
public static class Pair {
private double first;
private double second;
public Pair(double first, double second) {
this.first = first;
this.second = second;
}
public double getFirst() {
return first;
}
public double getSecond() {
return second;
}
}
public static Pair minmax(double[] values) {
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
for (double v : values) {
if (min > v) min = v;
if (max < v) max = v;
}
// 将获得的值传入Pair构造器
return new Pair(min, max);
}
}
放到接口中的任何类都自动地是public & static的,且在嵌套类中写一个测试函数main,方便
public interface ClassInFace {
void howdy();
class Test implements ClassInFace {
public void howdy() { println("fuckdy!");}
}
class TestMain {
public static void main(String[] args) {
new Test().howdy();
}
}
}
可以这样使用接口:
interface In {
String s();
String f();
class Nest {
static void get(ClassInFace c) {
println(c.s() + c.f());
}
}
}
public class ClassInFace implements In {
public String s() { return "fuck you!";}
public String f() { return "son of bitch!";}
public static void main(String[] args) {
ClassInFace c = new ClassInFace();
In.Nest.get(c);
}
}