讲完.class,Class之后,继续。
  
  1)泛化的Class引用
  
  Class也可以加入泛型,加入之后会进行类型检查。
  
  贴一下书上原话,Class<?>优于Class,虽然他们是等价的,Class<?>的好处是碰巧或疏忽使用了一个非具体的类引用。我搞不懂这个所谓非具体是什么?
  
  后面弄懂了,其实<?>作为通配符,就是未知的,直接写结论的话不能写个具体类型吧,作者的意思其实就是说加了泛型的Class就是选择了非具体的版本。
  
  加入泛型的原因是提供编译期间的类型检查,操作失误的话便会显示错误,但是使用普通的Class的时候,就要到等到运行的时候。
  
  还有这个Class<T>,JDK文档中:
  
  T - the type of the class modeled by thisClass object. For example, the type ofString.class isClass<String>. UseClass<?> if the class being modeled is unknown.
  
  <T>是使用泛型类的声明。包括:
  
  Interface List<E>
  
  Type Parameters:
  
  E - the type of elements in this list
  
  一样也是声明。
  
  2)转型语法
  
  SE5添加的用于Class引用转型的语法。
  
  [java] view plain copy print?
  
  class Gun{
  
  int price = 1;
  
  }
  
  class DeathGun extends Gun{
  
  int price = 2;
  
  }
  
  public class TestCast {
  
  public static void main(String[] args) {
  
  Gun g = new DeathGun();
  
  Class<DeathGun> d = DeathGun.class;
  
  //泛型的用处 类型不匹配
  
  //Class<DeathGun> dd = Gun.class;
  
  DeathGun gg = d.cast(g);
  
  System.out.println(gg.price);
  
  }
  
  }
  
  cast源码:
  
  public T cast(Object obj) {
  
  if (obj != null && !isInstance(obj))
  
  throw new ClassCastException(cannotCastMsg(obj));
  
  return (T) obj;
  
  }
  
  3)类型转换前的检查
  
  [java] view plain copy print?
  
  if(x instanceof TV){
  
  ((TV)x).show();
  
  }
  
  检查对象类型,向下转型时如果有错,则抛出ClassCastException,所以要先使用instanceOf。
  
  instaceOf与Class的等价性。
  
  [java] view plain copy print?
  
  class Father{}
  
  class Son extends Father{}
  
  public class Test {
  
  static void test(Object o ){
  
  System.out.println("type: "+o.getClass());
  
  System.out.println("o instanceof Father: "+(o instanceof Father));
  
  System.out.println("o instanceof Son: "+(o instanceof Son));
  
  System.out.println("Father.isInstanceOf(o)"+Father.class.isInstance(o));
  
  System.out.println("Son.isInstanceOf(o)"+Son.class.isInstance(o));
  
  System.out.println("o.getClass()==Father.class:"+(o.getClass()==Father.class));
  
  System.out.println("o.getClass()==Son.class:"+(o.getClass()==Son.class));
  
  System.out.println("o.getClass().equals(Father.class):"+(o.getClass().equals(Father.class)));
  
  System.out.println("o.getClass().equals(Son.class):"+(o.getClass().equals(Son.class)));
  
  }
  
  public static void main(String[] args) {
  
  test(new Father());
  
  test(new Son());
  
  }
  
  }
  
  result:
  
  type: class son.Father
  
  o instanceof Father: true
  
  o instanceof Son: false
  
  Father.isInstanceOf(o)true
  
  Son.isInstanceOf(o)false
  
  o.getClass()==Father.class:true
  
  o.getClass()==Son.class:false
  
  o.getClass(www.chuangshi88.cn/).equals(Father.class):true
  
  o.getClass().equals(Son.class):false
  
  type: class son.Son
  
  o instanceof Father: true
  
  o instanceof Son: true
  
  Father.isInstanceOf(o)true
  
  Son.isInstanceOf(o)true
  
  o.getClass(www.baqist.cn)==Father.class:false
  
  o.getClass(http://www.gbpcci.cn )==Son.class:true
  
  o.getClass(www.120xh.cn).equals(Father.class):false
  
  o.getClass(http://www.dwhxsl.cn).equals(Son.class):true
  
  instanceof指的是你是这个类吗?你是这个类的派生类吗?
  
  4)反射
  
  书上讲得好简单,3页左右。
  
  RTTI,运行时类型信息可以告诉你对象的具体类型,但是,这个类型必须在编译时必须已知,这样RTTI才能识别。即在编译时,编译器必须知道要通过RTTI来处理的类。
  
  这个看起来不是限制,但是置身于大规模的编程中,可能编译时程序无法获知这个对象所属的类。
  
  RTTI和反射真正的区别只有:RTTI,编译器在编译时检查和打开.class文件,对于反射,.class文件编译时不可获取,是在运行时打开和检查.class文件。
  
  直接用书上的例子,贴个代码:
  
  [java] view plain copy print?
  
  public class ShowMethods {
  
  private static String usage =
  
  "usage:\n" +
  
  "ShowMethods http://www.gouyily.cn/ 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) {
  
  System.out.println(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 == http://xucaizxyl.com/1) {
  
  for(Method method : methods)
  
  System.out.println(
  
  p.matcher(method.toString()).replaceAll(""));
  
  for(Constructor ctor : ctors)
  
  System.out.println(p.matcher(ctor.toString()).replaceAll(""));
  
  lines = methods.length + ctors.length;
  
  } else {
  
  //其实作者这样写是,method匹配会匹配,如果我java ShowMethods ShowMethods ShowMethods
  
  //本来的话是提取其中的一个,但是args[1]为ShowMethods,刚刚好匹配到的就是ShowMethods本身自带的方法,也就是main方法。
  
  for(Method method : methods)
  
  if(method.toString().indexOf(args[1]) != -1) {
  
  System.out.println(
  
  p.matcher(method.toString()).replaceAll(""));
  
  lines++;
  
  }
  
  for(Constructor ctor : ctors)
  
  if(ctor.toString().indexOf(args[1]) != -1) {
  
  System.out.println(p.matcher(
  
  ctor.toString(www.xyseo.net)).replaceAll(""));
  
  lines++;
  
  }
  
  }
  
  } catch(ClassNotFoundException e) {
  
  System.out.println("No such class: " + e);
  
  }
  
  }
  
  }
  
  F:\>java ShowMethods ShowMethods
  
  public static void main(String[])
  
  public final native Class getClass()
  
  public native int hashCode()
  
  public boolean equals(Object)
  
  public String toString()
  
  public final native void notify()
  
  public final native void notifyAll()
  
  public final native void wait(long) throws InterruptedException
  
  public final void wait(long,int) throws InterruptedException
  
  public final void wait() throws InterruptedException
  
  public ShowMethods()
  
  慢慢看Matcher的replaceAll方法,不同于String的replaceAll,后者有两个参数,一个替换内容,一个是要被替换的内容。而前者只有一个参数。
  
  public String replaceAll(String replacement)
  
  Replaces every subsequence of the input sequence that matches the pattern with the given replacement string.
  
  [java] view plain copy print?
  
  public class TestString {
  
  public static void main(String[] args) {
  
  String s = "0898((*(*))(";
  
  //正则表达式编译进Pattern
  
  Pattern p = Pattern.compile("\\W");
  
  //p.matcher返回的是Matcher对象,Matcher的replaceAll方法是可以将匹配的字符串
  
  //替换成方法参数中的内容。
  
  System.out.println(p.matcher(s).replaceAll("-"));
  
  }
  
  }
  
  result:0898--------
  
  如果没有正则表达式的替换,那么结果是:
  
  [java] view plain copy print?
  
  public static void ShowMethods.main(java.lang.String[])
  
  public final native java.lang.Class java.lang.Object.getClass()
  
  public native int java.lang.Object.hashCode()
  
  public boolean java.lang.Object.equals(java.lang.Object)
  
  public java.lang.String java.lang.Object.toString()
  
  public final native void java.lang.Object.notify()
  
  public final native void java.lang.Object.notifyAll()
  
  public final native void java.lang.Object.wait(long) throws java.lang.Interrupte
  
  dException
  
  public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedEx
  
  ception
  
  public final void java.lang.Object.wait() throws java.lang.InterruptedException
  
  public ShowMethods()
  
  其实就是替换掉类前面的包名。
  
  有没有发现,forName的结果在编译时不可知,我们是在运行的时候传进Class参数的。虽然刚开始的时候没用到这么高级的东西,但是后面学得深入了之后就发现有些东西在使用,如spring。
  
  getMethods拿到的是类的所有共有方法,包括自身,从父类继承,从接口实现的public方法。
  
  还有一个是getDeclaredMethods拿到的是类自身声明的方法,不止是public方法,protected也能拿到,甚至是private。(刚开始我也是很疑惑,不是经常强调封装,私有不让人家看到吗,怎么可以直接拿到private的东西的,其实可以这样看,什么东西有个度,但是这个度并不是一尘不破,有一定的后门)。
  
  getConstructors返回的是public的构造器。试了一下,私有的构造器不会显示。书上讲到这里就停了,继续扩展:
  
  以前看过Java反射教程里面介绍的很好。
  
  一、未知的方法调用
  
  [java] view plain copy print?
  
  public class TestRefl {
  
  public static void main(String[] args) {
  
  UnKnown uk = new UnKnown();
  
  Method m = null;
  
  try {
  
  m = uk.getClass().getMethod("print", new Class<?>[0]);
  
  m.invoke(uk);
  
  } catch (NoSuchMethodException | InvocationTargetException| SecurityException |IllegalAccessException e) {
  
  e.printStackTrace();
  
  }
  
  }
  
  }
  
  class UnKnown{
  
  public void print(){
  
  System.out.println("haha");
  
  }
  
  }
  
  之前我特地将方法改成private,发现是找不到方法的,只有改为public。
  
  二、对象的创建
  
  [java] view plain copy print?
  
  public class TestRefl {
  
  public static void main(String[] args) {
  
  Class c = null;
  
  try {
  
  c = c.forName("son.UnKnown");
  
  System.out.println(c.getName());
  
  } catch (ClassNotFoundException e) {
  
  System.out.println("not found");
  
  }
  
  try {
  
  UnKnown u = (UnKnown) c.newInstance();
  
  u.print();
  
  } catch (InstantiationException e) {
  
  e.printStackTrace();
  
  } catch (IllegalAccessException e) {
  
  e.printStackTrace();
  
  }
  
  }
  
  }
  
  class UnKnown{
  
  static void print(){
  
  System.out.println("haha");
  
  }
  
  }
  
  通过构造函数获取对象。
  
  [java] view plain copy print?
  
  public class TestRefl {
  
  public static void main(String[] args) {
  
  Class c = null;
  
  try {
  
  c = c.forName("son.UnKnown");
  
  } catch (ClassNotFoundException e) {
  
  System.out.println("not found");
  
  }
  
  Constructor<?> ct[] = c.getConstructors();
  
  try {
  
  UnKnown u = (UnKnown) ct[0].newInstance();
  
  UnKnown u2 = (UnKnown) ct[1].newInstance(1);
  
  u.print();
  
  u2.print();
  
  } catch (InstantiationException e) {
  
  // TODO Auto-generated catch block
  
  e.printStackTrace();
  
  } catch (IllegalAccessException e) {
  
  // TODO Auto-generated catch block
  
  e.printStackTrace();
  
  } catch (IllegalArgumentException e) {
  
  // TODO Auto-generated catch block
  
  e.printStackTrace();
  
  } catch (InvocationTargetException e) {
  
  // TODO Auto-generated catch block
  
  e.printStackTrace();
  
  }
  
  }
  
  }
  
  class UnKnown {
  
  public UnKnown() {
  
  }
  
  public UnKnown(int i) {
  
  }
  
  static void print() {
  
  System.out.println("haha");
  
  }
  
  }
  
  构造函数数组有顺序,0是无参的那个构造函数,1为传参,在方法中直接传参即可。当然私有的构造方法是拿不到的。
  
  解释到RTTI和反射的不同的时候,反过来可以说明反射的作用,就是运行时检查对象的类型,任意调用对象的方法(Spring和servlet中都用到了,注意到没有,我们在xml配置,然后属性会根据xml注入),同时可以知道方法参数和属性。
  
  反射还是很强大,接下来会介绍动态代理,以前被虐过的一个设计模式。
  
  顶
  
  0
  
  踩
  
  0

讲完.class,Class之后,继续。的更多相关文章

  1. (转)一个故事讲完https

    (转)一个故事讲完https 2 1  序言 今天来聊一聊https 安全传输的原理. 在开始之前,我们来虚构两个人物, 一个是位于中国的张大胖(怎么又是你?!), 还有一个是位于米国的Bill (怎 ...

  2. 猴博士4小时讲完C语言视频教程

    猴博士4小时讲完C语言视频教程,一共有9节课. 目录结构如下: 目录:/2020030-猴博士4小时讲完C语言 [1G] ┣━━1.C语言基本语句(上)(更多资源访问:www.jimeng365.cn ...

  3. 10 分钟讲完 QUIC 协议。

    建议阅读本文需要搭配作者 HTTP 相关文章食用. 历史 HTTP 系列文章: 看完这篇HTTP,跟面试官扯皮就没问题了 HTTP 2.0 ,有点炸 ! 这里先来回顾一下 HTTP 的发展过程.首先, ...

  4. Android学习之基础知识十三 — 四大组件之服务详解第二讲(完整版的下载示例)

    上一讲学习了很多关于服务的使用技巧,但是当在真正的项目里需要用到服务的时候,可能还会有一些棘手的问题让你不知所措.接下来就来综合运用一下,尝试实现一下在服务中经常会使用到的功能——下载. 在这一讲我们 ...

  5. 一口气讲完 LSA — PlSA —LDA在自然语言处理中的使用

    自然语言处理之LSA LSA(Latent Semantic Analysis), 潜在语义分析.试图利用文档中隐藏的潜在的概念来进行文档分析与检索,能够达到比直接的关键词匹配获得更好的效果. LSA ...

  6. 算法很美,听我讲完这些Java经典算法包你爱上她

    大家好,我是小羽. 对于编程来说的话,只有掌握了算法才是了解了编程的灵魂,算法对于新手来说的话,属实有点难度,但是以后想有更好的发展,得到更好的进阶的话,对算法进行系统的学习是重中之重的. 对于 Ja ...

  7. 参加完Rocket MQ Meetup深圳站,回顾和想法

    最近一段时间才开始关注云栖社区的公众号,在两周前看到要在深圳科兴科学园办一场Rocket MQ的Meetup.因为从来没有参加过这种线下活动,而且对Rocket MQ比较感兴趣,所以就立即报名参加. ...

  8. cache2go源码最后一讲 - examples

    先看一下我们讲到哪里了: cache2go的源码前面我们已经讲完了cacheitem和cachetable的实现,今天cahce和examples会一起讲完~ 1.cache.go源码 ​      ...

  9. 3.PO如何给开发团队讲好故事

    敏捷开发系列文章目录 讲出符合开发团队味口的故事. 上一章说了敏捷开发团队的构成与迭代过程,本章重点说一下迭代第一天的计划会议.熟话说“好的开始就成功了一半”,一个迭代的计划会议做得好不好确实直接注定 ...

随机推荐

  1. MVC5中EF6 Code First启动慢及间隙变慢的一些优化处理

    问题描述: 第一次访问的时候很慢,后面再次打开页面很快,过了一段时间不访问页面然后再次打开页面又像第一次那样很慢. 采用的技术和环境: 使用技术:EF6+MVC5 服务器环境:Windows 2012 ...

  2. 07 - Django应用第四步

    知识点 1) 表单的编写 CSRF问题 forloop.counter 2) 视图函数的知识 GET和POST HttpResponseRedirect的使用 reverse的使用 3) 通用视图 C ...

  3. Convolutional Neural Networks for Visual Recognition 8

    Convolutional Neural Networks (CNNs / ConvNets) 前面做了如此漫长的铺垫,现在终于来到了课程的重点.Convolutional Neural Networ ...

  4. 洛谷【P1090】合并果子&&洛谷【P1334】瑞瑞的木板

    浅谈堆:https://www.cnblogs.com/AKMer/p/10284629.html 合并果子题目传送门:https://www.luogu.org/problemnew/show/P1 ...

  5. 采用MySQL_upgrade升级授权表方式升级

    1.7.1 采用MySQL_upgrade升级授权表方式升级(1) 这种升级方式比较省事,通过MySQL_upgrade命令即可完成.下面来演示一下整个升级过程. 1)修改my.cnf配置文件,因为M ...

  6. 如何避免这个delete from tb_name不带条件的操作

    那么,我们如何避免这个delete from tb_name不带条件的呢?其实是有办法的,但这只针对运维DBA或者DBA在操作时候有用,但对于PHP和JAVA程序,它的连接操作方式,就没办法避免了 s ...

  7. 几个最短路径算法Floyd、Dijkstra、Bellman-Ford、SPFA的比较

        几大最短路径算法比较 转自:http://blog.csdn.net/v_july_v/article/details/6181485 几个最短路径算法的比较: Floyd        求多 ...

  8. uboot 命令使用教程(uboot参数设置)

    1. Printenv 打印环境变量. uboot> printenv baudrate=115200 ipaddr=192.168.0.111 ethaddr=32:34:46:78:9A:D ...

  9. PowerDesigner生成CDM模型

    一.新建概念数据模型  1)选择File-->New,弹出如图所示对话框,选择CDM模型(即概念数据模型)建立模型. 2)完成概念数据模型的创建.以下图示,对当前的工作空间进行简单介绍.(以后再 ...

  10. sql server 2008 开启1433端口,开启远程连接

    通常情况下只需要设置两处