详见:https://blog.csdn.net/zai_xia/article/details/80026325

扩展:java反射机制与动态加载类 https://www.cnblogs.com/wzk-0000/p/9322866.html

在讲解动态加载类之前呢,我们先弄清楚为什么要动态加载类,静态加载不行吗?我们可以看下面的实例:

我在文件夹里写了Office.java 类和 Word.java类,如下:

Office.java

class Office{
public static void main(String[] args){
if(args[0].equals("Word")){
Word w = new Word();
w.start();
}
if(args[0].equals("Excel")){
Excel e = new Excel();
e.start();
}
}

Word.java

class Word{
public void start(){
System.out.println("Word Start");
}

编译会报错,这当然没问题,因为确实没有写Excel.java类。

但是这个Excel类我们一定会用到吗?如果这个Excel类需要很久才能写出来,在此我们也不能使用其他功能吗?后面如果一个类出问题了,这个系统是不是就瘫痪了?

所以这就体现出动态加载类的好处了,动态加载类是按需加载的,你需要什么类,就加载什么类,一个类的状态,不会影响到另一个类的使用。

所以我们可以将Office类改造如下:

class Office{
public static void main(String[] args){
try{
Class c = Class.forName(args[0]);
Word w = (Word)c.newInstance();
w.start();
}
catch(Exception e){
e.printStackTrace();
} }

虽然我们还是没有写Excel类,但此时我们再编译Office.java文件,编译通过;

成功按照我们预想的结果运行,这样Word类就可以单独运行。

但是这样还是不够规范,因为现在只能加载Word类类型的类文件,为了使程序有更好的扩展性,我们添加一个接口,只有让所有的功能类实现该接口即可。完善如下:

OfficeAble.java

interface OfficeAble{
public void start();
}

Office.java

class Office{
public static void main(String[] args){
try{
Class c = Class.forName(args[0]);
OfficeAble oa = (OfficeAble)c.newInstance();
oa.start();
}
catch(Exception e){
e.printStackTrace();
} }

Word.java

class Word implements OfficeAble{
public void start(){
System.out.println("Word Start");
}
}

这样改造之后,我后面要添加一个Excel类,乃至添加其他的类,只需要实现OfficeAble接口就可以了,不需要改动Office这个类和其他的功能类,扩展性很强,这就是动态加载的优势。

扩展:java的反射机制与动态加载

什么是java反射机制?

1、当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射。
IT行业里这么说,没有反射也就没有框架,现有的框架都是以反射为基础。在实际项目开发中,用的最多的是框架,填的最多的是类,反射这一概念就是将框架和类揉在一起的调和剂。所以,反射才是接触项目开发的敲门砖。

2、java中的new方法是静态加载,因为new方法是在编译阶段就会检查,而不是在运行阶段。反射是可以在运行时创建对象,调用对象的方法、变量等。

3、Java反射机制主要提供了以下功能:在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。

例如:

package service.impl;

public class Test {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
F f = new F();
// 第一种表达方式
Class c1 = F.class;// 这种表达方式同时也告诉了我们任何一个类都有一个隐含的静态成员变量class
// 第二种表达方式
Class c2 = f.getClass();// 这种表达方式在已知了该类的对象的情况下通过getClass方法获取
// 第三种表达方式
Class c3 = Class.forName("service.impl.F");// 类的全称 System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c3.getName());
F temp = (F) c1.newInstance();//这里可以是c1/c2/c3
System.out.println(temp.f);
temp.save();
}
} class F {
public String f = "test"; public void save() {
System.out.println("save...");
}
}

运行结果

service.impl.F
service.impl.F
service.impl.F
test
save...

动态加载 。。。。

如果没有不带参数的构造函数,则不能通过c1.newInstance() 构造对象,需要先获取构造函数,再构造对象

       Class c = Class.forName("com.my.app.Book");

            Constructor con = c.getConstructor(String.class);

            Book book = (Book) con.newInstance("语文");

            System.out.println(book);

4.获取方法,运行方法:

package com.my.app;

public class Book {

    private String name ="金1瓶1梅";

    public Book() {
super();
} public Book(String name) {
super();
this.name = name;
} public void outDate(){
System.out.println("1111111 ");
} public void outDate(String string){
System.out.println("1111111 " +string);
} public void outDate(String string,int num){
System.out.println("1111111 " +string +" " +num);
} }
            Class c = Class.forName("com.my.app.Book");
Book book = (Book) c.newInstance();
book.outDate();
Method[] methods = c.getMethods(); Method method = c.getMethod("outDate", String.class,int.class); method.invoke(book, "6465465",55);       

        Method method = c.getMethod("outDate", String.class);

        method.invoke(book, "6465465");

获取变量

Class c = Class.forName("com.my.app.Book");
Book book = (Book) c.newInstance(); Field field1 = c.getField("price");//根据变量名,返回一个具体的具有public属性的成员变量 Field field2 = c.getDeclaredField("price");//根据变量名,返回一个成员变量(不分public和非public属性)
System.out.println(field1.getDouble(book)); System.out.println(field2.getName());//获取变量名
System.out.println(field2.getType());//获取变量类型
System.out.println(field2.get(book));//获取变量值
System.out.println(field2.getDouble(book));//获取变量值 //获取私有字段 模拟get set方法
Field nameField = c.getDeclaredField("name");
//取消访问私有字段的合法性检查
nameField.setAccessible(true); System.out.println(nameField.get(book)); nameField.set(book, "BBBB");
System.out.println(book);

最新文章

  1. java.lang.ExceptionInInitializerError /NoClassDefFoundError: [Lorg/hibernate/engine/FilterDefinition;
  2. TFS2012 自动生成与部署
  3. struts2 action配置时 method 省略不写 默认执行方法是父类ActionSuppot中的execute()方法
  4. 使用log4j将日志写入数据库并发送邮件
  5. leetcode面试准备:Triangle
  6. opencv视频跟踪2
  7. 在unity 脚本中获取客户端的IP地址
  8. EntityFrame Work 5 性能注意事项(转自MSDN)
  9. RSA加解密工具类RSAUtils.java,实现公钥加密私钥解密和私钥解密公钥解密
  10. Django Linux环境下部署CentOS7+Python3+Django+uWSGI+Nginx(含Nginx返回400问题处理、防火墙管理)
  11. HDU-2087-KMP-水题
  12. Twain Capabilities 转
  13. Hadoop HBase概念学习系列之META表和ROOT表(六)
  14. 【分享】Java学习之路:不走弯路,就是捷径
  15. 使用eclipse执行maven-release-plugin插件发布jar异常问题(.project)(Cannot prepare the release because you have local modifications )
  16. 绛河 初识WCF4
  17. 解决:win8.1 oepnvpn客户端 redirect-gateway def1无效,自动获取的IP没有网关问题
  18. SQL server 和 Oracle 中列转行的小操作
  19. 20155233 2006-2007-2 《Java程序设计》第2周学习总结
  20. atitit,it人怎么样才容易事业成功?? 有以下五种性格的人容易成功

热门文章

  1. Maven报错,没有有效的生命周期
  2. 20175215 2018-2019-2 第五周java课程学习总结
  3. JavaScript_AMD规范
  4. 【转】unity3d优化总结篇
  5. 一、基础篇--1.1Java基础-hashCode和equals方法的区别和联系
  6. 十四:jinja2过滤器之常用的过滤器
  7. PC端网页嵌入百度地图
  8. 利用jquery的淡入淡出函数(fadeIn和fadeOut)--实现轮播
  9. java:LeakFilling(JSP,servlet,Ajax,Json,Path)
  10. Elastic search中使用nested类型的内嵌对象