JAVA 复习(Think In Java, 4th) -- Inner Classes - Part2
2014-10-05 16:07
501 查看
Anonymous Inner Class
一般耒说,我们先实现接口,实现了以後,我们再从事相关的数据运算,如:
「创建一个继承该 Interface的对象」,代码如下,它的意义其实和上面的代码是一样的:
其实这就像是 Android 的 View.OnClickListener() 的实现
而我们工作时一般尽量不用这种匿名类方式实现,拿个例子耒说:
Template Design Pattern。
回到 Inner Classes的复习~我在练习的过程中,想试著放一些参数给 Anonymous Inner Class,但是就如下面看到的,Anonymous Class 的实现接口是不能放参数的(因为 Inner这个接口本身的Constructor就没有能放参数的),因为它是使用类的缺省(default) Constructor。
我们如果要放参数的话,也是可以的,就直接另外定义一个实现该接口的类,同时让它的建构子
能放我们需要的参数就行了,如下:
虽然实现了,但这样就不是匿名类的做法了(有了 MyInner类),匿名类的做法,是在宣告一个 abstract class,
并且在该 abstract class实现构造函数,达到初始化的目的,如下:
有了以上匿名类的基础知识後,我们可以改写一下JAVA 复习(Think In Java, 4th) -- Interface文中工厂方法
(Factory Method)模式的代码:
修改後:
Nested Classes
当你的内部类对象和其所在的外部类对象没有什麽关系的时候,可以考据把你的内部类加上 static 属性,
加上 static 後的内部类又叫 nested class, 当你这麽做的时候,代表二件事:
一、内部类对象不用再依靠创建外部类对象以後再创建内部类对象。
二、内部类对象不能再存取外部类的 non-static 类成员(因为内部类有了 static 属性)
练习的时候发现假如在nested class 里再宣告一个 nested class,用下面的方式就会出错:
其实应该用下面这种方式来做:
Closures & callbacks
Closure 指的是一个自产生到结束的过程都存在,并持有资讯数据的可呼叫物件。
而在这一章,我们可以发现 Inner Class 便是个物件导向的 Closure。
从下面的代码可以看到,mOnClickListener 透过 setOnClickListener()而和外界得已接触,外界可自行实现一个接口传入,从而
有不同的 Click 事件的処理。而在本例 OnClickListener 所触发的事件已被 JavaClosure 类实现,我们可以创一个内部类,
另外实现一个方法。
其它:
http://stackoverflow.com/questions/26029272/nested-class-as-testing-method-in-java
一般耒说,我们先实现接口,实现了以後,我们再从事相关的数据运算,如:
public class AInner { public interface Inner { public String getMsg(); } public class MyInner implements Inner { private String msg; public MyInner() { msg = "I am anonymous innner class!"; } public String getMsg() {return msg;} } public Inner inner() { return new MyInner(); } public static void main(String[] args) { AInner ai = new AInner(); Inner c = ai.inner(); System.out.println(c.getMsg()); } }但是 AnonyMous Inner Class 可以让我们直接返回一个匿名类的对象,而不用宣告一个类,并实现该接口,它的意思也就是说
「创建一个继承该 Interface的对象」,代码如下,它的意义其实和上面的代码是一样的:
public class AInner { public interface Inner { public String getMsg(); } public Inner inner() { return new Inner() { private String msg = "I am anonymous innner class!"; public String getMsg(){return msg;} }; } public static void main(String[] args) { AInner ai = new AInner(); Inner c = ai.inner(); System.out.println(c.getMsg()); } }
其实这就像是 Android 的 View.OnClickListener() 的实现
// 看看 OnClickListener, 其实是个 interface /** * Interface definition for a callback to be invoked when a view is clicked. */ public interface OnClickListener { /** * Called when a view has been clicked. * * @param v The view that was clicked. */ void onClick(View v); } // 而我们有时也就这麽用: ...blablabla... mView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { ....blablabla.... } }); ... blablabla...
而我们工作时一般尽量不用这种匿名类方式实现,拿个例子耒说:
... mViewA.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { 処理方式A(); } }); mViewB.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { 処理方式B(); } }); mViewC.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { 処理方式C(); } }); ... 依此类推...按上面这种实现方式的话,如果有 N 个可被点击的 View,那可能最多会有 N 个匿名类对象,而这些对象在程序运行时,都是占系统资源的,因此我们一般尽量这麽做
public class xxx extends ooo implements View.OnClickListener { ... @Override public void onClick(View v) { final int vid = v.getId(); switch(vid) { case R.id.buttona: 処理事件A(); break; case R.id.buttonb: 処理事件B(); break; .... default:break; } } ... }或是宣告一个 View.OnClickListener 的对象,然後让多个 View 引用。不同的処发事件,则使用覆写不同的 OnClick() 方法,以解决不同的需求,这便是典型的
Template Design Pattern。
回到 Inner Classes的复习~我在练习的过程中,想试著放一些参数给 Anonymous Inner Class,但是就如下面看到的,Anonymous Class 的实现接口是不能放参数的(因为 Inner这个接口本身的Constructor就没有能放参数的),因为它是使用类的缺省(default) Constructor。
//: innerclasses/Parcel7.java // Returning an instance of an anonymous inner class. public class Parcel7 { public Contents contents(final String name) { return new Contents(name) { // Insert a class definition private String mName = name; private int i = 11; public int value() { return i; } public String getName(){ return mName;} }; // Semicolon required in this case } public static void main(String[] args) { Parcel7 p = new Parcel7(); Contents c = p.contents(); System.out.println(""+c.getName()); } } ///:~
我们如果要放参数的话,也是可以的,就直接另外定义一个实现该接口的类,同时让它的建构子
能放我们需要的参数就行了,如下:
public class AInner { public interface Inner { public String getMsg(); } public class MyInner implements Inner { private String mMsg; public MyInner(String msg) { mMsg = msg; } public String getMsg(){ return mMsg; } } public Inner inner(final String msg) { return new MyInner(msg); } public static void main(String[] args) { AInner ai = new AInner(); Inner c = ai.inner("hi"); System.out.println(c.getMsg()); } }
虽然实现了,但这样就不是匿名类的做法了(有了 MyInner类),匿名类的做法,是在宣告一个 abstract class,
并且在该 abstract class实现构造函数,达到初始化的目的,如下:
public class AInnerPrac { public abstract class People { public People(String name) { // 把 Constructor 该做的事实现在这里 System.out.println("new fighter: " + name); } public abstract void run(); } public People getPeople(final String name) { return new People(name) { @Override public void run() { System.out.println(name + " is running and fighting!"); } }; } public static void main(String[] args) { AInnerPrac ap = new AInnerPrac(); People p = ap.getPeople("Shanwu"); p.run(); } }
public class AInnerPrac { public abstract class People { private String mName; // 多了这个就不用 getPeople(final String name) 了 public People(String name) { mName = name; System.out.println("new fighter: " + mName); } public abstract void run(); public String getName() { return mName; } // 直接把参数传进这个类 } public People getPeople(String name) { return new People(name) { @Override public void run() { System.out.println(getName() + " is running and fighting!"); } }; } public static void main(String[] args) { AInnerPrac ap = new AInnerPrac(); People p = ap.getPeople("Shanwu"); p.run(); } }
有了以上匿名类的基础知识後,我们可以改写一下JAVA 复习(Think In Java, 4th) -- Interface文中工厂方法
(Factory Method)模式的代码:
interface provideCoffee { String getCoffeeType(); void makeCoffee(); } class VanillaCoffee implements provideCoffee { @Override public String getCoffeeType() { return "Vanilla--Flavor Coffee"; } @Override public void makeCoffee() { String action = "make "+getCoffeeType()+" coffee"; System.out.println(action); } } class ChocolateCoffee implements provideCoffee { @Override public String getCoffeeType() { return "Chocolate--Flavor Coffee"; } @Override public void makeCoffee() { String action = "make "+getCoffeeType()+" coffee"; System.out.println(action); } } class Customer { void getServed(provideCoffee coffee) { coffee.makeCoffee(); String action = "Customer drinks "+ coffee.getCoffeeType(); System.out.println(action); } } public class StarBucks { public static void main(String[] args) { Customer a = new Customer(); a.getServed(new VanillaCoffee()); a.getServed(new ChocolateCoffee()); } }
修改後:
interface provideCoffee { String getCoffeeType(); void makeCoffee(); } interface CoffeeMaker { provideCoffee readyForCoffee(); } class VanillaCoffee implements provideCoffee { @Override public String getCoffeeType() { return "Vanilla--Flavor Coffee"; } @Override public void makeCoffee() { String action = "make "+getCoffeeType()+" coffee"; System.out.println(action); } public static CoffeeMaker coffeeMaker = new CoffeeMaker() { @Override public provideCoffee readyForCoffee() { return new VanillaCoffee(); } }; } class ChocolateCoffee implements provideCoffee { @Override public String getCoffeeType() { return "Chocolate--Flavor Coffee"; } @Override public void makeCoffee() { String action = "make "+getCoffeeType()+" coffee"; System.out.println(action); } public static CoffeeMaker coffeeMaker = new CoffeeMaker() { @Override public provideCoffee readyForCoffee() { return new ChocolateCoffee(); } }; } class Customer { void getServed(CoffeeMaker cmaker) { provideCoffee coffee = cmaker.readyForCoffee(); coffee.makeCoffee(); String action = "Customer drinks "+ coffee.getCoffeeType(); System.out.println(action); } } public class StarBucks { public static void main(String[] args) { Customer a = new Customer(); a.getServed(VanillaCoffee.coffeeMaker); a.getServed(ChocolateCoffee.coffeeMaker); } }
Nested Classes
当你的内部类对象和其所在的外部类对象没有什麽关系的时候,可以考据把你的内部类加上 static 属性,
加上 static 後的内部类又叫 nested class, 当你这麽做的时候,代表二件事:
一、内部类对象不用再依靠创建外部类对象以後再创建内部类对象。
二、内部类对象不能再存取外部类的 non-static 类成员(因为内部类有了 static 属性)
练习的时候发现假如在nested class 里再宣告一个 nested class,用下面的方式就会出错:
public class NestedClassPrac { public static class Nested { public void sayHello() { System.out.println("First nested class~");} public static class LittleNested { public void sayHello() { System.out.println("this is why we are nested class");} } } public static void main(String[] args) { Nested a = new Nested(); a.sayHello(); LittleNested b = new Nested(); b.sayHello(); } }
其实应该用下面这种方式来做:
public class NestedClassPrac { public static class Nested { public void sayHello() { System.out.println("First nested class~");} public static class LittleNested { public void sayHello() { System.out.println("this is why we are nested class");} } } public static void main(String[] args) { Nested a = new Nested(); a.sayHello(); Nested.LittleNested b = new Nested.LittleNested(); b.sayHello(); } }
Closures & callbacks
Closure 指的是一个自产生到结束的过程都存在,并持有资讯数据的可呼叫物件。
而在这一章,我们可以发现 Inner Class 便是个物件导向的 Closure。
从下面的代码可以看到,mOnClickListener 透过 setOnClickListener()而和外界得已接触,外界可自行实现一个接口传入,从而
有不同的 Click 事件的処理。而在本例 OnClickListener 所触发的事件已被 JavaClosure 类实现,我们可以创一个内部类,
另外实现一个方法。
interface OnClickListener { void onClick(); } public class JavaClosure implements OnClickListener { private OnClickListener mOnClickListener; public void setOnClickListener(OnClickListener l) { mOnClickListener = l; } public void click() { System.out.println("clicked"); if(mOnClickListener!=null) { mOnClickListener.onClick(); } } @Override public void onClick() { System.out.println("hello! I am listener!!"); } public OnClickListener getType2ClickEvent() { return new Type2ClickListener(); } private static class Type2ClickListener implements OnClickListener { @Override public void onClick() { System.out.println("hello! I am type 2 listener!!"); } } public static void main(String[] args) { JavaClosure jcbtn = new JavaClosure(); jcbtn.setOnClickListener(jcbtn); jcbtn.click(); jcbtn.setOnClickListener(jcbtn.getType2ClickEvent()); jcbtn.click(); } }
其它:
http://stackoverflow.com/questions/26029272/nested-class-as-testing-method-in-java
相关文章推荐
- JAVA 复习(Think In Java, 4th) -- Inner Classes - Part1
- JAVA 复习(Think In Java, 4th) -- Arrays - part1
- JAVA 复习(Think In Java, 4th) -- Error Handling with Exceptions
- JAVA 复习(Think In Java, 4th) -- Interface
- JAVA 复习(Think In Java, 4th)-- Holding Your Object
- JAVA 复习(Think In Java, 4th) -- File I/O -- Part 1
- JAVA 复习(Think In Java, 4th)-- Holding Your Object
- JAVA 复习(Think In Java, 4th) -- File I/O -- part 2
- 看think in java 4th持有对象一章的Map小结,因为一个例子,重新总结下hashCode()和equals(),加深印象。
- 数据结构复习笔记(Data Structures & Algorithms in Java, 4th) --Garbage Collection
- Think In Java 笔记6 Inner Classes
- Think in Java 4th--Java中的volatile
- 现在开始研究java,主攻Think in java 4th
- 读书笔记 Think in Java 4th 第十一章 持有对象 List、Set、Queue和Map
- 如何下载并使用think in java 4th中的源代码
- 读书笔记 Think in Java 4th 第三章 操作符
- Think in java 答案_Chapter 3_Exercise 4
- Think in java 答案_Chapter 3_Exercise 1
- Think in java 答案_Chapter 2_Exercise 10
- Think in java 答案_Chapter 3_Exercise 2