Java动态特性和多态

Java动态特性和JVM有关,和应用代码也有关系。

Java动态特性:

JVM方法调用的静态(static binding) 和动态绑定机制(auto binding),
  01.编译阶段就能够确定调用哪个方法的方式,我们叫做 静态绑定机制,
    私有方法、静态方法、构造器及初始化方法<clinit>都是采用静态绑定机制。
   在编译器阶段就已经指明了调用方法在常量池中的符号引用,JVM运行的时候只需要进行一次常量池解析
  02.动态机制
    类加载机制
    反射
    动态代理
    注解

1.类加载机制

ClassLoader
    01.类路径 类名
    02.启动类加载器
        Bootstrap  ClassLoader
        Extension  ClassLoader  Java 9增加了Platform Class Loader
        Application ClassLoader
    03.加载顺序
 应用
    示例:Tomcat 利用自定义的ClassLoader 实现应用隔离,以及支持JSP和OSGI实现动态模块化的基础
     即实现隔离和热部署

2.反射

Class 入口类
 import java.lang.Class
    Class 有一个静态方法 forName
       forName有两个
           forName(String className)
           forName(String name, boolean initialize, ClassLoader loader)
        eg
          : Class.forName("com.mysql.jdbc.Driver")
          等价于 forName("com.mysql.jdbc.Driver", true, currentLoader)
           currentLoader = ?

3.动态代理

静态代理:代理类直接定义在代码中
动态代理: 动态生成代理类
01.JDK内置的动态代理 Proxy类 面向接口
02.第三方代理: cglib 动态代理 -通过继承实现,面向一个具体的类,实现AOP框架
  cglib

4.注解

01.创建注解
    元注解: @Target @Retention @Document @Inherit
    @interface
        String[] value() ;
        如果注解只有一个成员,则成员名必须取名为value(),使用时可以忽略成员名和赋值号
示例
  JDK内置的注解
    --没有成员的注解称为 标识注解
  第三方框架的注解
   Spring
    @Service
   Junit
     @Test

02.注解的使用
  @
  作用二:
    自动处理源代码以产生更多的源代码-配置文件-脚本或者其他我们想要的东西
    例如-使用注解,根据模板来生成不同源码
03.注解的应用
RUNNING 中的情况
    DI容器
      DI的容器类-创建需要的对象并配置依赖关系
        使用代码
            SimpleContainer.getInstance(ServiceA.class).callB();
        底层代码:注解工具内部处理机制
            注解如何被处理的,在运行时的处理过程
04.Hibernate 注解

5.加载资源

文件路径问题以及获取资源文件的方法
    绝对路径和相对路径
        1. 本地系统的绝对路径          2.URI形式的绝对资源路径
        1.相对于classpath的相对路径    2.相对于当前用户目录的相对路径
   01.JAVA运行时,首先会在指定的类路径下(classpath路径下)搜索JAVA编译后的字节码文件(class文件),
        然后通过类加载器加载到虚拟机中
     this.getClass().getClassLoader().getResource("template");
       path不能以'/'开头时;
       path是从ClassPath根下获取;
    02.this.getClass().getResource 是得到当前对象对应的类文件(*.class)所在的目录下的文件
       this.getClass.getResource("")
         path不以'/'开头时,默认是从此类所在的包下取资源;
         path  以'/'开头时,则是从ClassPath根下获取;
    03.Thread.currentThread().getContextClassLoader().getResource("")
    示例:
        System.out.println(this.class.getResource("/")); //到classes目录    加了前缀 file
        System.out.println(this.class.getResource("")); //到具体包所在目录  加了前缀 file
        System.out.println(this.class.getClassLoader().getResource("")); //到classes目录   加了前缀 file
        System.out.println(this.class.getClassLoader().getResource("/")); // null
  04.getResource  返回URL对象
      .getResourceAsStream 是返回所在文件的流 InputStream
      this.getClass().getClassLoader().getResource("template");
      this.class.getClassLoader().getResourceAsStream 来获取InputStream
        load(InputStream inStream)、load(Reader reader)
        this.getClass().getClassLoader().getResource("").openStream()
加载资源
Resources 类为从类路径中加载资源,提供了易于使用的方法
     对于简单的只读文本数据,加载为 Reader。
     对于简单的只读二进制或文本数据,加载为 Stream。
     对于可读写的二进制或文本文件,加载为 File。
     对于只读的配置属性文件,加载为 Properties。
     对于只读的通用资源,加载为 URL

其他

    起初 标准API的一部分的所有内容都是java包的一部分,而不是标准API一部分的所有内容都是在包名javax下发布的,
 随着时间的推移,作为javax发布的扩展成为Java API的组成部分。
 但是,将扩展从javax包移动到java包将是太麻烦了,最终会破坏一堆现有的代码。因此,最终决定javax包将成为标准API的一部分
 是历史遗留的问题

动态特性与多态

多态
1. 示例
private Map<String, Map<String, String>> configMap = new HashMap<String, Map<String, String>>();

List<String> keyList = new ArrayList<String>(dataMap.keySet());
 Collections.sort(keyList); 
Map.Entry<String, String> entry : Map<String, String> map.entrySet()

示例2:
定义一个接口类型的引用变量 来 引用实现接口的类的实例,当这个引用调用方法时,
它会根据实际引用的类的实例来判断具体调用哪个方法。
 该方法必须已经在接口中被声明,而且在接口的实现类中该实现方法的类型和参数必须与接口中所定义的精确匹配。
   //定义接口InterA  
   interface InterA  {  void fun();  }  
   //实现接口InterA的类B  
   class B implements InterA  {  public void fun()  {System.out.println(“This is B”);  }  
   //实现接口InterA的类C  
   class C implements InterA  { public void fun()  {System.out.println(“This is C”);   }  }  
    //主类main
   class Test  { public static void main(String[] args)  {   InterA a;   a= new B();  a.fun();  a = new C();    a.fun();  }}

  示例
      设计模式中有:“代码尽量依赖于抽象,不依赖于具体.代码依赖于抽象的好处是,代码可以方便替换。
      例如,代码
    List list = new ArrayList();下面通过list来操作集合。代码编写后发现集合使用的不准确,
       应该使用LinkedList,那么只要修改一行代码
   List list = new LinkedList();就可以,这行以后的代码不需要修改,
       因为List接口保证了调用的都是接口中的方法,而ArrayList与LinkedList都实现了List接口     
    说明:
      01.ArrayList list = new ArrayList()这种形式的话,
        那么list访问到的就可能是ArrayList里独有的方法而非List接口中的方法。
       这样替换成LinkedList的时候就有可能需要修改很多的代码   
      02.因为存放在ArrayList里的值都转换成了Object类型,
      所以 使用ArrayList内部的值时,必须强制转换才行
         List<String>  list =   new ArrayList<String>();
        List<String> list = (String)new ArrayList(); 强制类型转换

Java中类型转换

   Java中强制类型转换分为基本数据类型和引用数据类型两种
       1.基本数据类型: 
             01.自动类型转换,也称隐式类型转换
             02.强制类型转换,也称显式类型转换,是指必须书写代码才能完成的类型转换。
                该类类型转换很可能存在精度的损失,
                   所以必须书写相应的代码,并且能够忍受该种损失时才进行该类型的转换
       2.引用类型的强转
         父类转换为子类的强制类型转换是有条件的:
            父类强制转换为子类时只有当引用类型真正的身份为子类时才会强制转换成功
                 Father father = new Son();  不报错
                 Son son = (Son)father;

                 Father father = new  Father(); 报错-ClassCastException
                 Son son = (Son) father;

                 Father father =  null ;
                 Son son = (Son) father;

blogroll

social