一、为什么需要RTTI
Run-Time Type Information。通过运行时类型信息,程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。
编程应该尽量面向接口编程,应该对类型信息尽量的少了解
package tij.classinfomation;
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<Shape> shapeList = Arrays.asList(new Circle(), new Square(),
new Triangle());
for (Shape shape : shapeList) {
shape.draw();
}
}
}
abstract class Shape {
void draw() {
System.out.println(this + ".draw");
}
abstract public String toString();
}
class Circle extends Shape {
public String toString() {
return "Circle";
}
}
class Square extends Shape {
public String toString() {
return "Square";
}
}
class Triangle extends Shape {
public String toString() {
return "Triangle";
}
}
二、Class对象
看书,书上写得好
package tij.classinfomation;
public class Test {
public static void main(String[] args) {
System.out.println("inside main");
new Candy();
System.out.println("After creating Candy");
try {
Class<Gum> clazz = Gum.class;
String class_name = clazz.getName();
System.out.println(class_name);
Class.forName(class_name);
} catch (ClassNotFoundException e) {
System.out.println("Couldn't find Gum");
}
System.out.println("After Class.forname(\"Gum\")");
new Cookie();
System.out.println("After creating Cookies");
}
}
class Candy {
static {
System.out.println("Loading Candy");
}
}
class Gum {
static {
System.out.println("Loading Gum");
}
}
class Cookie {
static {
System.out.println("Loading Cookie");
}
}
静态语句块在这个类被加载的时候运行。
其中Class.forName方法中要写类的绝对路径,包名+类名,同时调用Gum.class.getName的时候,也并没有加载Gum类。
另外
class tt{
static void showt(){
System.out.println("showt");
}
static{
System.out.println("ttstatic");
}
}
class jj extends tt{
static void showj(){
System.out.println("showj");
}
static{
System.out.println("jjstatic");
}
}
public class Test {
public static void main(String[] args) {
jj.showt();
}
}
虽然调用的事jj.showt,但是并没有加载jj这个类,而是加载了tt这个类。
所以就验证了,运行时是实际用谁了,才加载谁
package tij.classinfomation;
public class Test {
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("tij.classinfomation.FancyToy");
} catch (ClassNotFoundException e) {
System.out.println("Can't find FancyToy");
System.exit(1);
}
ToyTest.printInfo(c);
System.out.println("-----------------");
for (Class face : c.getInterfaces()) {
ToyTest.printInfo(face);
}
System.out.println("-----------------");
Class up = c.getSuperclass();
Object obj = null;
try {
obj = up.newInstance();
} catch (InstantiationException e) {
System.out.println("Cannot instantiate");
System.exit(1);
} catch (IllegalAccessException e) {
System.out.println("Cannot access");
System.exit(1);
}
ToyTest.printInfo(obj.getClass());
}
}
interface HasBatteries {}
interface Waterproof {}
interface Shoots {}
class Toy {
Toy() {}
Toy(int i) {}
}
class FancyToy extends Toy implements HasBatteries, Waterproof, Shoots {
FancyToy() {
super(1);
}
}
class ToyTest {
static void printInfo(Class cc) {
System.out.println("Class name:" + cc.getName() + " is interface?["
+ cc.isInterface() + "]");
System.out.println("Simple name:" + cc.getSimpleName());
System.out.println("Canonical name:" + cc.getCanonicalName());
}
}
看书
1.类字面常量
类字面常量就是
FancyToy.class;
基本类型也可以用的,这个方法不会自动初始化这个类对象
要使用类的话,要进行三个步骤
package tij.classinfomation;
import java.util.Random;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class initable = Initable.class;
System.out.println("After Initable ref");
System.out.println(Initable.staticFinal);
System.out.println(Initable.staticFinal2);
System.out.println(Initable2.staticNonFinal);
Class initable3 = Class.forName("tij.classinfomation.Initable3");
System.out.println("After creating Initable3 ref");
System.out.println(Initable3.staticNonFinal);
}
}
class Initable {
static final int staticFinal = 47;
static final int staticFinal2 = new Random(47).nextInt(1000);
static {
System.out.println("Initializing Initable");
}
}
class Initable2 {
static int staticNonFinal = 147;
static {
System.out.println("Initializing Initable2");
}
}
class Initable3 {
static int staticNonFinal = 74;
static {
System.out.println("Initializing Initable3");
}
}
2.泛化的Class引用
Class<Number> genericIntClass=int.class;
这是错的
Class<? extends Number> genericIntClass = Integer.class;
这个可以
Class<?> genericIntClass = Integer.class;
有个<?>比class光杆优雅
package tij.classinfomation;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
FilledList<CountedInteger> fl = new FilledList<>(CountedInteger.class);
System.out.println(fl.create(15));
}
}
class CountedInteger {
private static long counter;
private final long id = counter++;
public String toString() {
return Long.toString(this.id);
}
}
class FilledList<T> {
private Class<T> type;
public FilledList(Class<T> type) {
this.type = type;
}
public List<T> create(int nElements) {
List<T> result = new ArrayList<T>();
for (int i = 0; i < nElements; i++) {
try {
result.add(type.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
}
B.class.getSuperclass()指的是“某各类,且是B的父类”
Class<A>指的是“A类”
这两个是有区别的
3.新的转型语法
没啥卵用= =就是类型装换嘛
三、类型转换前先做检查
看书吧= =这段太费劲了。
四、注册工厂
要在已有的继承关系中添加新的继承关系,最合适的就是应该将新添加的类再父类中完成注册。
结合工厂设计模式
package tij.classinfomation;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Test {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(Part.createRandom());
}
}
}
class Part {
public String toString() {
return this.getClass().toString();
}
static List<Factory<? extends Part>> partFactories = new ArrayList<>();
static {
partFactories.add(new FuelFilter.Factory());
partFactories.add(new AirFilter.Factory());
partFactories.add(new CabinAirFilter.Factory());
partFactories.add(new FanBelt.Factory());
}
private static Random rand = new Random(47);
static Part createRandom() {
int n = rand.nextInt(partFactories.size());
return partFactories.get(n).create();
}
}
interface Factory<T> {
T create();
}
class Filter extends Part {}
class FuelFilter extends Filter {
public static class Factory
implements
tij.classinfomation.Factory<FuelFilter> {
public FuelFilter create() {
return new FuelFilter();
}
}
}
class AirFilter extends Filter {
public static class Factory
implements
tij.classinfomation.Factory<AirFilter> {
public AirFilter create() {
return new AirFilter();
}
}
}
class CabinAirFilter extends Filter {
public static class Factory
implements
tij.classinfomation.Factory<CabinAirFilter> {
public CabinAirFilter create() {
return new CabinAirFilter();
}
}
}
class Belt extends Part {}
class FanBelt extends Belt {
public static class Factory
implements
tij.classinfomation.Factory<FanBelt> {
public FanBelt create() {
return new FanBelt();
}
}
}
任何新添加的子类,只要在part类中新添加一个add就可以完成注册了。
另外此处运用到了工厂方法,往列表里添加的也是一个工厂对象,这样的意义在于将创建对象的任务交给各个对象自己的工厂来办,利用多态的性质,在新添加的类中相似实现工厂可以达到生成新的子类的对象的目的。
五、instanceof与Class的等价性
package tij.classinfomation;
public class Test {
public static void main(String[] args) {
FamilyVsExactType.test(new Derived());
FamilyVsExactType.test(new Base());
}
}
class Base {}
class Derived extends Base {}
class FamilyVsExactType {
static void test(Object x) {
print("Tseting x of type " + x.getClass());
print("x instanceof Base " + (x instanceof Base));
print("x instanceof Derived " + (x instanceof Derived));
print("Base.isInstance(x) " + (Base.class.isInstance(x)));
print("Derived.isInstance(s) " + Derived.class.isInstance(x));
print("x.getClass()==Base.class " + (x.getClass() == Base.class));
print("x.getClass().equals(Base.class) "
+ (x.getClass().equals(Base.class)));
print("x.getClass()==Derived.class " + (x.getClass() == Derived.class));
print("x.getClass().equals(Derived.class) "
+ (x.getClass().equals(Derived.class)));
}
static void print(String s) {
System.out.println(s);
}
}
六、反射:运行时的类信息
package tij.classinfomation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
public class Test {
private static String usage = "usage:\n"
+ "ShowMethods qualified.class.name\n"
+ "To show all methods in class or:\n"
+ "ShowMethods qualified.class.name word\n"
+ "To search for methods involving 'word'";
private static Pattern p = Pattern.compile("\\w+\\.");
public static void main(String[] args) {
Class<?> c = Test.class;
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(p.matcher(method.toString()).replaceAll(""));
}
Constructor[] ctors = c.getConstructors();
for (Constructor constructor : ctors) {
System.out
.println(p.matcher(constructor.toString()).replaceAll(""));
}
}
}
七、动态代理
package tij.classinfomation;
public class Test {
public static void main(String[] args) {
Interface Aface = new RealObject();
Aface.doSomething();
Aface.somethingElse("bonobo");
System.out.println("------------");
Interface Bface = new SimpleProxy(Aface);
Bface.doSomething();
Bface.somethingElse("bonobo");
}
}
interface Interface {
void doSomething();
void somethingElse(String arg);
}
class RealObject implements Interface {
public void doSomething() {
System.out.println("doSomething");
}
public void somethingElse(String arg) {
System.out.println("somethingElse " + arg);
}
}
class SimpleProxy implements Interface {
private Interface proxied;
public SimpleProxy(Interface proxied) {
this.proxied = proxied;
}
public void doSomething() {
System.out.println("SimpleProxy doSomething");
proxied.doSomething();
}
public void somethingElse(String arg) {
System.out.println("SimpleProxy somethingElse " + arg);
proxied.somethingElse(arg);
}
}
我觉得这块讲的不是很好,CZ那边这里讲的就很好。
八、空对象
没懂= =
end
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。