而Java反射机制能够动态地成立对象并调用其性质

2019-10-06 作者:编程   |   浏览(182)
1.写SQL语句

Jacob 是 JAVA-COM Bridge的缩写,是一个中间件,能够提供自动化访问MS系统下COM组件和Win32 libraries的功能。

反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。Oracle官方对反射的解释是

最近因为自己毕业的一些事情断更了简书,一转眼已经有两个月了,是时候给自己充一波电了。本篇主要 复习 总结一些多线程中的基础知识,开篇打算理清一些概念性的东西,如有理解错误的地方,欢迎各位指正。

2.获取连接
  • MS系统提供的COM组件

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

并发与并行是一对相似而又有区别的的两个概念。并行是指两个或多个事件在同一时刻发生,只有在多CPU环境下才有可能发生。并发是指在一段时间内宏观上有多个程序在同时运行,但实际上每个程序只是在CPU分配的时间片内运行,每一时刻也只能由一道程序执行。

3.创建PreparedStatement
COM组件 对象ID
MS Word Word.Application
MS Excel Excel.Application
MS Powerpoint Powerpoint.Application
MS IE InternetExplore.Application

简而言之,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而Java反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。 反射的核心是JVM在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。

使用并发编程的目的是为了让程序运行的更快,但是,并不是启动更多的线程就能让程序运行的更快,这取决于代码的质量和应用场景。抛开并发代码的质量不谈,如果应用场景不得当,并发也不一定比串行的程序快,因为线程有创建和上下文切换的开销。这里不再深入,如果感兴趣可以《Java并发编程艺术》第一章中找到例子。

4.执行sql语句

a)更新b)查询

  • 核心类

    • JacobObject:用于Java程序MS下的COM进行通信,创建标准的API框架

    • ComThread:初始化COM组件线程,释放线程,对线程进行管理

    • Dispatch:调度处理类,封装了操作来从而操作Office,并表示不同MS级别调度对象

    • ActiveXComponent : 创建COM组件

    • Variant : 与COM通讯的参数或者返回值

    • ROT :Running Object Table ,运行对象表将每个线程映射到所有jacobobjects,在线程创建

  • 核心方法

    • 小鱼儿玄机30码,Dispatch : 可调用该自动化对象的属性或方法,具体的属性和方法要看参考文档VBA API

      • Dispatch.get(dispatch, String name);获取对象属性
      • Dispatch.put(dispatch, String name, Object value);设置对象属性
      • Dispatch.call(dispatch, String name, Object… args);调用对象方法
  • 类图

    小鱼儿玄机30码 1Jacob类图

Java反射框架主要提供以下功能:

首先上一段最基本的对于线程的使用:

5.关闭/异常

BaseDao是自己写的通用的dao父类,自己写的所有的dao都继承这个父类dao

小鱼儿玄机30码 2流程图

  • 判断任意对象所属的类;
  • 获取一个类的任意对象(获得Class对象);
  • 获取一个类所具有的任意成员变量和方法;
  • 构造任意一个对象以及调用一个对象
public class ThreadTest { public static void main(String... args){ new Thread-> System.out.println(Thread.currentThread().getName .start(); new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName.start(); }}// 输出:// Thread-0// Thread-1
通用方法
  • ###### 更新类别的:update , delete , insert

  • ###### 查询类别的

  • 优点

    • 相对于OpenOffice,转换效果良好,
    • 相对于POI,可以操作Word/Powerpoint
    • 使用简单,参照VBA API即可使用Jacob操作COM组件

这里说的获取特质运行时,既编译之后的行为。通俗的讲就是我们可以获取Android 系统所有内部类,private方法 变量,@hide 的方法和变量 @internal 的方法和变量。。。

上面的例子创建了两个线程,分别打印了两条线程的名字。Thread的构造函数可以接受一个Runable参数,这个Runnable主要就是执行用户任务的代码。代码很简单,没什么好多说的。接下来还是来看一段代码和输出结果,来引入并发可能引发的问题。

代码中用到元数据方法简书地址:数据库之元数据——DatabaseMetaData
package com.eu.dss.dao;import com.eu.dss.util.ConnUtil;import java.util.List;import org.apache.commons.beanutils.BeanUtils;import java.sql.*;import java.util.ArrayList;/** * Created by 马欢欢 on 2017/5/18. */public class BaseDao { private Connection conn; private PreparedStatement pstmt; private ResultSet rs; /** * 更新的通用方法 * 更新的sql语句(update/insert/delete) * paramsValue sql语句中占位符对应的值(如果没有占位符,传入null) */ public void update(String sql, Object[] paramsValue) { try { //获取连接 conn = ConnUtil.getConnextion(); //创建执行任务 pstmt = conn.prepareStatement; //参数元数据: 得到占位符参数的个数 int count = pstmt.getParameterMetaData().getParameterCount(); //判断是否有条件 if (paramsValue != null && paramsValue.length > 0) { //循环给参数赋值 for (int i = 0; i < count; i  ) { pstmt.setObject(i   1, paramsValue[i]); } } pstmt.executeUpdate(); } catch (Exception e) { throw new RuntimeException; } finally { ConnUtil.close(null, pstmt, conn); } } /** * 查询通用方法 */ public <T> List<T> query (String sql, Object[] paramsValue , Class<T> tClass){ List <T> list = new ArrayList<T>(); //获取连接 conn = ConnUtil.getConnextion(); try { //创建对象 pstmt = conn.prepareStatement; int count = pstmt.getParameterMetaData().getParameterCount(); if(paramsValue !=null && paramsValue.length> 0 ){ for(int i=0;i<paramsValue.length;i  ){ pstmt.setObject(i 1,paramsValue[i]); } } rs = pstmt.executeQuery(); //拿到结果集元数据 ResultSetMetaData rsmd = rs.getMetaData(); //获取列的个数 int culumnCount =rsmd.getColumnCount(); T t; while){ t = tClass.newInstance(); for (int i = 0; i<culumnCount;i  ){ String coulumnName =rsmd.getColumnName; Object value = rs.getObject(coulumnName); BeanUtils.copyProperty(t,coulumnName,value); } list.add; } return list; } catch (Exception e) { e.printStackTrace(); } return null; }}

DAO层: 下来我们在写Dao层的代码时就特别简单

下面示例:

  • 查询数据
  • 查找数据按照id
  • 插入数据
  • 更新数据
  • 删除数据
package com.eu.dss.dao.impl;import com.eu.dss.dao.BaseDao;import com.eu.dss.dao.ITronClassDao;import com.eu.dss.entity.TronClasstype;import net.sf.json.JSONArray;import java.util.List;/** * Created by 马欢欢 on 2017/5/23. */public class TronClassDao extends BaseDao implements ITronClassDao { public List<TronClasstype> TronClasstype() { String sql = " SELECT * FROM eu_tronclass ; "; List <TronClasstype> list = super.query(sql,null,TronClasstype.class); JSONArray jsonArray = JSONArray.fromObject; System.out.println("bbbb" jsonArray); return list; } public TronClasstype findByid { String sql = " SELECT * FROM eu_tronclass where id=? ; "; List <TronClasstype> list = super.query(sql,new Object[id],TronClasstype.class); return (list!=null && list.size ? list.get : null; } public void save(TronClasstype tronClassType) { String sql = " INSERT INTO eu_tronclass (year,tron_month,eu_rj,eu_xin,eu_rw,eu_ts,eu_xiu,eu_gz,eu_kuai,eu_ad,eu_wc,eu_wu,eu_jr) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?); "; Object[] paramsValue = {tronClassType.getYear(),tronClassType.getTron_month(), tronClassType.getEu_rj(), tronClassType.getEu_xin(), tronClassType.getEu_rw(), tronClassType.getEu_ts(), tronClassType.getEu_xiu(), tronClassType.getEu_gz(), tronClassType.getEu_kuai(), tronClassType.getEu_ad(), tronClassType.getEu_wc(), tronClassType.getEu_wu(), tronClassType.getEu_jr()}; super.update(sql,paramsValue); } public void update(TronClasstype tronClassType ) { String sql = " UPDATE eu_tronclass SET year = ?,tron_month =?,eu_rj =?,"   "eu_xin =?,eu_rw=?,eu_ts=?,eu_xiu=?,eu_gz=?,eu_kuai=?,"   "eu_ad=?,eu_wc=?,eu_wu=?,eu_jr=? where id=?"; Object[] paramsValue = {tronClassType.getYear(),tronClassType.getTron_month(), tronClassType.getEu_rj(), tronClassType.getEu_xin(), tronClassType.getEu_rw(), tronClassType.getEu_ts(), tronClassType.getEu_xiu(), tronClassType.getEu_gz(), tronClassType.getEu_kuai(), tronClassType.getEu_ad(), tronClassType.getEu_wc(), tronClassType.getEu_wu(), tronClassType.getEu_jr(), tronClassType.getId()}; super.update(sql,paramsValue); } public void delete { String sql = " delete from eu_tronclass where id =? "; Object[] paramsValue = {id}; super.update(sql,paramsValue); }}

Internal和hidden API的区别:Hidden API之所以被隐藏,是想阻止开发者使用SDK中那些未完成或不稳定的部分。举个例子,Bluetooth API在API 5(Android 2.0)上才开放;在API 3 和4上都是用@hide属性隐藏了。当这些API被验证和清理后,Google的开发者会移除@hide属性,并让其在API 5官方化。很多地方在API 4 和5之间发生了变化。如果你的程序依赖某些隐藏的API,当其部署到新的平台上时,就有可能陷入困境。对于internal API来说,从来都没有计划将其开放出来。它就是Android的“内部厨房”,对开发者来说,应该将其视作黑盒。凡事都会有变化的。如果你依赖某些internal API,也有可能在新的Android release上,这些internal API发生变化,从而令你失望。

总结一下区别:Hidden API = 进行中的工作;Internal API = 黑盒;

public class SaleTicket implements Runnable { public static final int TICKET_TOTAL = 100; private int tickets = 100; @Override public void run() { while (tickets > 0) { try { sale(); } catch (InterruptedException e) { e.printStackTrace(); } } } public void sale() throws InterruptedException { if (tickets > 0) { tickets--; System.out.println(Thread.currentThread().getName()   "卖出 第"   (TICKET_TOTAL - tickets)   "张票"); Thread.sleep; } } public static void main(String... args) { SaleTicket saleTicket = new SaleTicket(); new Thread(saleTicket, "一号窗口").start(); new Thread(saleTicket, "二号窗口").start(); new Thread(saleTicket, "三号窗口").start(); }}

文章文集:JavaEE--学习笔记

  • 不足

    • 转换速度慢
    • CPU占用率高(单CPU占用100%)
    • 并发情况下WORD可能会死锁
    • Word宏安全问题

方法有三种使用Class类的forName静态方法:

小鱼儿玄机30码 3卖票.png

方法:public static Class<?> forName(String className)java 调用: Class.forName("XXX.XXX.XXX");

代码比较简单,模拟卖票,只要有余票就可以继续卖。可以看到当我使用三个线程模拟三个窗口卖票时出现了一个奇怪的现象,就是有一个时刻三个窗口都卖出了第八张票,这显然不符合正常的预期。聪明的你肯定能想到是我代码写的不对,的确,我的代码并不是线程安全的代码。关于线程安全,有很多定义,在维基百科上是这么说的:指某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成。非常正确,然而看完什么信息也没得到的定义……不过没事,现在就算放一个信息量巨大的定义给你,你也看不懂,先了解下就好。

直接获取某一个对象的class,比如:

接下来需要思考一些问题,为什么上面的代码会不安全?这个锅我们可以轻易的丢给多线程、并发,“因为多线程并发访问修改tickets变量,导致结果不可预期”,这么说也没错,不过太笼统了。这段代码是在我的电脑上跑的,我的电脑只有一个CPU,虽说是并发,但是到CPU层面上,也是串行执行的,那么为什么会出现上面图片中奇怪的情况呢?

本文由小鱼儿玄机30码发布于编程,转载请注明出处:而Java反射机制能够动态地成立对象并调用其性质

关键词: 小鱼儿玄机30码