`
dasheng
  • 浏览: 149073 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

<java编程思想>学习笔记14 第14章 类型信息

阅读更多

1,运行时类型信息使得你可以在程序运行时发现和使用类型信息。

 

2,运行时识别对象和类的信息有两种方式:第一种方式:

 

传统的“RTTI”,它假定我们在编译时已经知道了所有的类型;第二种方式是“反射”机制,它允许我们在运行时发现和

 

使用类的信息。

 

3,为什么需要RTTI

 

面向对象的编程的基本目的是:让代码只操纵对基类的引用:

 

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"; }

public class Shapes {
  public static void main(String[] args) {
    List<Shape> shapeList = Arrays.asList(
      new Circle(), new Square(), new Triangle()
    );
   
for(Shape shape : shapeList)
      shape.draw();
  }
} /* Output:

RTTI名字含义:在运行时,识别一个对象的类型。

 

 使用RTTI,可以查询某个Shape引用所指向的对象的确切类型,然后选择或者剔除特例。

 

4,Class对象

 

     Class对象就是用来创建类的所有的“常规”对象的

 

        所有的类都是在其第一次使用时,动态加载到JVM中的。当程序创建第一个对类的静态成员的引用时,就会动态加载

 

这个类。这个证明了构造器也是类的静态方法,即使在构造器之前并没有static关键字。因此,使用new操作符创建新的类

 

对象也会被当做对类的静态成员的引用。

 

      因此,java程序在它开始运行之前并非被完全加载,其各个部分是必需时才加载的。这一点与许多传统的语言不通。

 

动态加载的行为,在诸如c++这样的静态的加载语言中是很难或者根本不可能复制。

 

      类加载器首先检查这个类的Class对象是否已经加载,如果还没加载,默认的类加载器就会根据类名查找.class文件

 

(例如,某个附加类加载器可能会在数据库中查找字节码)。在这个类的字节码被加载时,它们会接受验证,以确保没有被

 

破坏,并且不包含不良的java代码。这是java中用于安全防范的措施之一。

 

class Candy {
  static { print("Loading Candy"); }
}

class Gum {
  static { print("Loading Gum"); }
}

class Cookie {
  static { print("Loading Cookie"); }
}

public class SweetShop {
  public static void main(String[] args) { 
    print("inside main");
    new Candy();
    print("After creating Candy");
    try {
     
Class.forName("Gum");
    } catch(ClassNotFoundException e) {
      print("Couldn't find Gum");
    }
    print("After Class.forName(\"Gum\")");
    new Cookie();
    print("After creating Cookie");
  }
} /* Output:

 

输出结果是:

 

inside main
Loading Candy
After creating Candy
Loading Gum
After Class.forName("Gum")
Loading Cookie
After creating Cookie

Class对象仅在需要的时候才被加载,static初始化是在类加载的时候进行。

 

无论何时,只有你想在运行时使用类型信息,就必须首先获得对恰当的Class对象的引用。Class.forName()就是实现此

 

方法的便捷途径,因为你不需要为了获得Class引用而持有该类型的对象。但是,如果你已经拥有了这个类型的对象,那就

 

可以用过调用getClass()方法来获得Class引用,这个方法属于跟类Object的一部分,它将返回表示该对象的实际类型

 

的Class引用。

 

interface HasBatteries {}
interface Waterproof {}
interface Shoots {}

class Toy {
  // Comment out the following default constructor
  // to see NoSuchMethodError from (*1*)
  Toy() {}
  Toy(int i) {}
}

class FancyToy extends Toy
implements HasBatteries, Waterproof, Shoots {
  FancyToy() { super(1); }
}

public class ToyTest {
  static void printInfo(Class cc) {
    print("Class name: " + cc.getName() +   //获得全限定的类名
      " is interface? [" + cc.isInterface() + "]");//是否是接口
    print("Simple name: " +
cc.getSimpleName());//获得不含包名的类名
    print("Canonical name : " + cc.getCanonicalName());//获得全限定的类名
  }
  public static void main(String[] args) {
    Class c = null;
    try {
      c = Class.forName("typeinfo.toys.FancyToy");
    } catch(ClassNotFoundException e) {
      print("Can't find FancyToy");
      System.exit(1);
    }
    printInfo(c); 
    for(Class face : c.getInterfaces()) //获得所有接口
      printInfo(face);
    Class up =
c.getSuperclass();//查询直接基类
    Object obj = null;
    try {
      // Requires default constructor:
      obj = up.newInstance(); //生成对象,必须带默认的构造器。


    } catch(InstantiationException e) {
      print("Cannot instantiate");
      System.exit(1);
    } catch(IllegalAccessException e) {
      print("Cannot access");
      System.exit(1);
    }
    printInfo(obj.getClass());
  }
} /* Output:

 

虚拟构造器:我不知道你的确切类型,但是无论如何要正确的创建你自己。使用newInstance()来创建的类,必须

 

带默认的构造器。

 

5,类字面构造器

 

.class生成Class对象的引用。对于基本类型还有字段TYPE。如下所示:

 

=等价 =等价
boolean.class Boolean.TYPE
char.class Charater.TYPE
byte.class Byte.TYPE
short.class Short.TYPE
int.class Integer.TYPE
long.class Long.TYPE
float.class Float.TYPE
double.class Double.TYPE
void.class Void.TYPE

 

使用类必须要准备三个步骤:

 

1,加载,这是由类加载器执行的。该步骤还将查找字节码,并从这些字节码中创建一个Class对象;

 

2,链接。在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必须的话,将解析这个类的创建的对其他类

 

的所有引用。

 

3,初始化,如果该类有超类,则对其初始化,执行静态初始化器和静态初始化块。

 

class Initable {
  static final int staticFinal = 47;
  static final int staticFinal2 =
    ClassInitialization.rand.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");
  }
}

public class ClassInitialization {
  public static Random rand = new Random(47);
  public static void main(String[] args) throws Exception {
    Class initable = Initable.class;
    System.out.println("After creating Initable ref");
    // Does not trigger initialization:
    System.out.println(Initable.staticFinal);
    // Does trigger initialization:
    System.out.println(Initable.staticFinal2);
    // Does trigger initialization:
    System.out.println(Initable2.staticNonFinal);
    Class initable3 = Class.forName("Initable3");
    System.out.println("After creating Initable3 ref");
    System.out.println(Initable3.staticNonFinal);
  }
} /* Output:

 

输出结果是:

 

After creating Initable ref
47
Initializing Initable
258
Initializing Initable2
147
Initializing Initable3
After creating Initable3 ref
74

 

6, 泛化类引用

 

public class GenericClassReferences {
  public static void main(String[] args) {
    Class intClass = int.class;
    Class<Integer> genericIntClass = int.class;
    genericIntClass = Integer.class; // Same thing
    intClass = double.class;
    // genericIntClass = double.class; // Illegal
  }
} ///:~

 

通过使用泛型语法,可以让编译器强制执行额外的类型检查。

 

7,新的转型语法cast

 

public class ClassCasts {
  public static void main(String[] args) {
    Building b = new House();
    Class<House> houseType = House.class;
    House h = houseType.cast(b);
    h = (House)b; // ... or just do this.
  }
} ///:~

 

 

8,类型转换前检查

 

我们知道的RTTI形式包括

1,传统的类型转换,如“(shape)”,由RTTI确保类型的正确性。

 

2,代表对象类型的Class对象。通过查询Class对象可以获得运行时所需的信息。

 

3,使用关键字 instanceof ,它返回一个布尔值,告诉我们对象是不是一个特定类型的实例。

 

if(x instanceof Dog)

  ((Dog) x) .bark();

 

public class PetCount {
  static class PetCounter extends HashMap<String,Integer> {
    public void count(String type) {
      Integer quantity = get(type);
      if(quantity == null)
        put(type, 1);
      else
        put(type, quantity + 1);
    }
  } 
  public static void
  countPets(PetCreator creator) {
    PetCounter counter= new PetCounter();
    for(Pet pet : creator.createArray(20)) {
      // List each individual pet:
      printnb(pet.getClass().getSimpleName() + " ");
     
if(pet instanceof Pet)
        counter.count("Pet");
      if(pet instanceof Dog)
        counter.count("Dog");
      if(pet instanceof Mutt)
        counter.count("Mutt");
      if(pet instanceof Pug)
        counter.count("Pug");
      if(pet instanceof Cat)
        counter.count("Cat");
      if(pet instanceof Manx)
        counter.count("EgyptianMau");
      if(pet instanceof Manx)
        counter.count("Manx");
      if(pet instanceof Manx)
        counter.count("Cymric");
      if(pet instanceof Rodent)
        counter.count("Rodent");
      if(pet instanceof Rat)
        counter.count("Rat");
      if(pet instanceof Mouse)
        counter.count("Mouse");
      if(pet instanceof Hamster)
        counter.count("Hamster");
    }
    // Show the counts:
    print();
    print(counter);
  } 
  public static void main(String[] args) {
    countPets(new ForNameCreator());
  }
} /* Output:

 

动态的instaceof

 

public class PetCount3 {
  static class PetCounter
  extends LinkedHashMap<Class<? extends Pet>,Integer> {
    public PetCounter() {
      super(MapData.map(LiteralPetCreator.allTypes, 0));
    }
    public void count(Pet pet) {
      // Class.isInstance() eliminates instanceofs:
      for(Map.Entry<Class<? extends Pet>,Integer> pair
          : entrySet())
    
    if(pair.getKey().isInstance(pet))
          put(pair.getKey(), pair.getValue() + 1);
    } 
    public String toString() {
      StringBuilder result = new StringBuilder("{");
      for(Map.Entry<Class<? extends Pet>,Integer> pair
          : entrySet()) {
        result.append(pair.getKey().getSimpleName());
        result.append("=");
        result.append(pair.getValue());
        result.append(", ");
      }
      result.delete(result.length()-2, result.length());
      result.append("}");
      return result.toString();
    }
  } 
  public static void main(String[] args) {
    PetCounter petCount = new PetCounter();
    for(Pet pet : Pets.createArray(20)) {
      printnb(pet.getClass().getSimpleName() + " ");
      petCount.count(pet);
    }
    print();
    print(petCount);
  }
} /* Output:

 

9,instanceof和Class的等价性

 

public class FamilyVsExactType {
  static void test(Object x) {
    print("Testing 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(x) " +
      Derived.class.isInstance(x));
    print("x.getClass() == Base.class " +
      (x.getClass() == Base.class));
    print("x.getClass() == Derived.class " +
      (x.getClass() == Derived.class));
    print("x.getClass().equals(Base.class)) "+
      (x.getClass().equals(Base.class)));
    print("x.getClass().equals(Derived.class)) " +
      (x.getClass().equals(Derived.class)));
  }
  public static void main(String[] args) {
    test(new Base());
    test(new Derived());
  } 
} /* Output:

 

输出结果如下:

 

nstanceof Base true
x instanceof Derived false
Base.isInstance(x) true
Derived.isInstance(x) false
x.getClass() == Base.class true
x.getClass() == Derived.class false
x.getClass().equals(Base.class)) true
x.getClass().equals(Derived.class)) false
Testing x of type class Derived
x instanceof Base true
x instanceof Derived true
Base.isInstance(x) true
Derived.isInstance(x) true
x.getClass() == Base.class false
x.getClass() == Derived.class true
x.getClass().equals(Base.class)) false
x.getClass().equals(Derived.class)) true

 

10 反射:运行时的类信息

 

类方法提取器:

 

public class ShowMethods {
  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) {
    if(args.length < 1) {
      print(usage);
      System.exit(0);
    }
    int lines = 0;
    try {
      Class<?> c = Class.forName(args[0]);
    
  Method[] methods = c.getMethods();
      Constructor[] ctors = c.getConstructors();
      if(args.length == 1) {
        for(Method method : methods)
          print(
            p.matcher(method.toString()).replaceAll(""));
        for(Constructor ctor : ctors)
          print(p.matcher(ctor.toString()).replaceAll(""));
        lines = methods.length + ctors.length;
      } else {
        for(Method method : methods)
          if(method.toString().indexOf(args[1]) != -1) {
            print(
              p.matcher(method.toString()).replaceAll(""));
            lines++;
          }
        for(Constructor ctor : ctors)
          if(ctor.toString().indexOf(args[1]) != -1) {
            print(p.matcher(
              ctor.toString()).replaceAll(""));
            lines++;
          }
      }
    } catch(ClassNotFoundException e) {
      print("No such class: " + e);
    }
  }
} /* Output:

 

11,动态代理

 

class DynamicProxyHandler implements InvocationHandler {
  private Object proxied;
  public DynamicProxyHandler(Object proxied) {
    this.proxied = proxied;
  }
  public Object
  invoke(Object proxy, Method method, Object[] args)
  throws Throwable {
    System.out.println("**** proxy: " + proxy.getClass() +
      ", method: " + method + ", args: " + args);
    if(args != null)
      for(Object arg : args)
        System.out.println("  " + arg);
    return method.invoke(proxied, args);
  }

class SimpleDynamicProxy {
  public static void consumer(Interface iface) {
    iface.doSomething();
    iface.somethingElse("bonobo");
  }
  public static void main(String[] args) {
    RealObject real = new RealObject();
    consumer(real);
    // Insert a proxy and call again:
   
Interface proxy = (Interface)Proxy.newProxyInstance(
      Interface.class.getClassLoader(),
      new Class[]{ Interface.class },
      new DynamicProxyHandler(real));
    consumer(proxy);
  }
} /* Output: (95% match) 

 

12,反射可以访问隐藏类型

 

public class HiddenImplementation {
  public static void main(String[] args) throws Exception {
    A a = HiddenC.makeA();
    a.f();
    System.out.println(a.getClass().getName());
    // Compile error: cannot find symbol 'C':
    /* if(a instanceof C) {
      C c = (C)a;
      c.g();
    } */
    // Oops! Reflection still allows us to call g():
    callHiddenMethod(a, "g");
    // And even methods that are less accessible!
    callHiddenMethod(a, "u");
    callHiddenMethod(a, "v");
    callHiddenMethod(a, "w");
  }
  static void callHiddenMethod(Object a, String methodName)
  throws Exception {
    Method g = a.getClass().getDeclaredMethod(methodName);
    g.setAccessible(true);
    g.invoke(a);
  }
} /* Output:

 

输出结果:

 

public C.f()
typeinfo.packageaccess.C
public C.g()
package C.u()
protected C.v()
private C.w()

分享到:
评论

相关推荐

    Java编程思想笔记(全)

    第十四章探讨了Java中的反射机制。反射允许程序在运行时获取类的信息并操纵对象的状态。本章讲解了Class对象的使用方法、如何获取类的方法和字段信息、如何动态创建对象以及调用方法等内容。通过反射,可以实现更为...

    Java/JavaEE 学习笔记

    第十四章 标准I/O流与文件.............84 第十五章 网络编程.89 Tiger学习笔记..................94 第一章 Java5.0新特性.......................94 第二章 基础知识.....96 第三章 泛型...........101 第四章 ...

    java学习心得,笔记,思想

    理解如何创建和使用类,以及如何通过对象间的相互作用实现功能,是Java编程的关键。 接着,我们来看一下Java集合框架,这是处理数据集合的强大工具。ArrayList、LinkedList、HashSet、HashMap等是常用的数据结构,...

    java实战经典学习笔记

    ### Java实战经典学习笔记知识点概览 #### 一、Java概述及开发环境搭建 - **Java概述** - Java是一种广泛使用的高级编程语言,由Sun Microsystems于1995年发布。 - Java的设计目标是“一次编写,到处运行”,这...

    java私塾学习笔记整理

    ### Java私塾学习笔记整理 #### 第一章:Java入门 **一、Java是什么?** Java是一种广泛使用的高级编程语言,由Sun Microsystems于1995年推出。它旨在为跨平台开发提供一种通用的语言环境,使开发者能够在任何...

    JAVA经典教材笔记

    - Java作为一种广泛使用的编程语言,其学习路径包括掌握基本语法、理解面向对象编程思想、熟悉标准库使用等。 - **JAVA发展概述** - Java的发展历程:从1995年由Sun Microsystems公司发布以来,Java经历了多次重大...

    J2EE学习笔记(J2ee初学者必备手册)

    第十四章 标准I/O流与文件.............84 第十五章 网络编程.89 Tiger学习笔记..................94 第一章 Java5.0新特性.......................94 第二章 基础知识.....96 第三章 泛型...........101 第四章 ...

    thinkinjava源码-ThinkingInJava:《Java编程思想4th》学习笔记Notesandsourcecodesaboutt

    本资源包含了这本书第四版的学习笔记和源代码,旨在帮助读者更好地理解和掌握Java编程思想。以下是对这些知识点的详细阐述: 1. **面向对象编程(OOP)**:Java是一种纯面向对象的语言,它强调类、对象、封装、继承...

    张龙 java se课程笔记

    【Java SE课程笔记详解】 Java SE(Standard Edition)是Java平台的核心版本,它为开发桌面应用、服务器端...通过深入学习和实践,你可以扎实掌握Java编程基础,为进一步深入学习Java EE或Android开发打下坚实的基础。

    2023年java基础总结大全笔记.doc

    Java是一种广泛使用的编程语言,以其跨平台性和强大的功能而闻名。以下是对《2023年Java基础总结大全笔记》的详细...以上就是对Java基础的详尽解析,涵盖了从基本概念到高级特性的多个方面,是学习Java编程的良好起点。

    牛人的spring学习笔记,非常适合初学者

    ### 牛人的Spring学习笔记,非常适合初学者 #### 第一课:面向抽象编程 面向抽象编程是一种编程思想,强调在程序设计过程中通过定义抽象层来分离业务逻辑与具体实现细节。这种方式有助于提高软件的可维护性和扩展...

    八种编程语言毕业设计参考文献

    《JSP&Servlet学习笔记》**(2012):通过作者的学习笔记形式,详细记录了JSP和Servlet的学习过程和心得,适合自学。 7. **刘京华.《JavaWeb整合开发王者归来》**(2010):介绍了JavaWeb开发的各种技术,并且强调了...

    郝斌java视频课代码及课件

    通过他的课程,学员不仅可以学习到Java语言的基本语法和特性,还能深入理解面向对象编程思想,以及如何实际应用这些知识去解决实际问题。 在"【1-3】源代码"中,我们可以预见到课程的起始阶段,通常会介绍Java环境...

    java参考文献

    Java编程思想[M]. 第4版. 机械工业出版社. - 内容概述:本书是Java领域内的一本经典著作,深入浅出地介绍了Java编程的基本概念、面向对象编程思想以及设计模式等内容。 - 关键知识点: - 面向对象编程(OOP)的...

    spring2.5_学习笔记.

    ### Spring2.5 学习笔记知识点概览 #### 第一课:面向抽象编程 - **概念理解**:面向抽象编程是一种设计模式,其核心思想是通过定义接口或抽象类来实现程序结构的设计,使具体实现与接口分离,增强系统的灵活性和...

    spring框架案例学习文档笔记

    ### Spring框架案例学习文档笔记知识点总结 #### 第一课:面向抽象编程 - **核心概念**:面向抽象编程强调的是程序设计中通过抽象接口来进行设计和实现的方式,它避免了直接依赖具体实现类,增强了系统的灵活性和可...

    【藏宝图】(珍藏版)2012java开发工程师必备精品资料(115)

    通过25天的学习,学员可以熟悉Java语言的基本语法、面向对象编程思想以及常用的API等内容。 #### 十二、《JAVA开发实战经典》随书视频及源码 这本书及其配套视频和源码资料是Java开发者的宝贵资源,内容涵盖了Java...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 第一章 Oracle入门 一、 数据库概述 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今五十年前。简单来说是本身可视...

    面向对象设计与构造PPT

    面向对象设计与构造是计算机科学领域中的核心课程,特别是在Java编程语言的学习中占有重要地位。本课程涵盖了多个关键知识点,旨在帮助学生理解并掌握面向对象编程的基本原理和实践技巧。 首先,从标题“面向对象...

    高性能高并发服务器架构大全

    3.1 第四层交换简介 214 3.2 硬件实现 215 3.3 软件实现 215  网站架构的高性能和可扩展性 233  资料收集:高并发 高性能 高扩展性 Web 2.0 站点架构设计及优化策略 243  CommunityServer性能问题浅析 ...

Global site tag (gtag.js) - Google Analytics