Reflection
类加载器
(classloader)
——用来加载
.class
文件
bootstrap(
引导指令
)—
能加载所有加载器,但他不能被任何人所加载,我们永远拿不到它,他是万物之母。
Jdk/jre./lib/rt.jar
Extclassloader(
可扩展的类加载器
)—
他被
bootstrap
所加载,他能加载
jdk/jre/lib/ext
目录下的所有
.jar
文件的类
.(jar
命令打包
)
Appclassloader(classpath
类加载器
)
——被
Extclassloader
所加载,平时用得最多的也就是他。
自定义类加载器
(
扩展某个类加载器
)
——注意一下,自定义的类加载器是被
classpath
类加载器所加载的。搜索
jdk
目录
classloader
有关的文件
,
可以看到许多类加载器的
java
文件,选择
URLClassLoader
扩展
.
代码见
(Demo),
可以看到把类文件放到我们自定义类加载器的目录下面,即可以被加载了!
要点:静态成员在同一个线程被同一个类加载器加载的情况下只有一个副本,但是被多个线程或多个类加载器加载的情况下就有多个副本。这就关系到一个隔离性的问题,
JDK
为了防止这种现象发生,不同的线程多个类加载器加载的类的对象之间不能够相互访问!
一个类加载器实例:
import
java.net.
*
;
import java.io. * ;
public class MyClassLoader extends URLClassLoader {
private static File file=new File("e:/temp/");
public MyClassLoader(){
super(getURL());
}
public static URL[] getURL(){
URL[] url=null;
try{
url=new URL[]{file.toURL()};
}catch(Exception e){
e.printStackTrace();
}
return url;
}
}
import java.io. * ;
public class MyClassLoader extends URLClassLoader {
private static File file=new File("e:/temp/");
public MyClassLoader(){
super(getURL());
}
public static URL[] getURL(){
URL[] url=null;
try{
url=new URL[]{file.toURL()};
}catch(Exception e){
e.printStackTrace();
}
return url;
}
}
List<String>
——这是指泛型集合对象。
JAVA
共享的静态块中到底有什么?有除了具体的非静态成员的值以外的所有,包括非静态成员方法,属性,静态方法,属性
,
类的实例
…..
六种获得类对象的方法
:
1.
From getClass().
i.
String str = "abc";
ii.
Class c1 = str.getClass();
2.
From the method Class.getSuperclass()
i.
Button b = new Button();
ii.
Class c1 = b.getClass();
iii.
Class c2 = c1.getSuperclass();
BTW getSuperclass() returns null for the class Object.
3.
From the static method Class.forName()
——运行时加载类对象
Class c1 = Class.forName ("java.lang.String");
Class c2 = Class.forName ("java.awt.Button");
Class c3 = Class.forName
("java.util.LinkedList$Entry");
Class c4 = Class.forName ("I");
Class c5 = Class.forName ("[I");
4.
From the .class syntax
类的构造
Class c1 = String.class;
Class c2 = java.awt.Button.class;
Class c3 = Main.InnerClass.class;
Class c4 = int.class;
Class c5 = int[].class;
5.
From the primitive wrapper classes
原始类型的包装类
Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Character.TYPE;
Class c4 = Short.TYPE;
Class c5 = Integer.TYPE;
Class c6 = Long.TYPE;
Class c7 = Float.TYPE;
Class c8 = Double.TYPE;
Class c9 = Void.TYPE;
6
.通过类加载器直接加载
.class
文件获得类对象
.
要点:如果要取得一个属性的值,必须给定一个对象,因为在静态块中他并不知道这个属性到底属于哪个具体的类对象:
Width.set(r,newWidth)
其中
r
就是具体的类对象,
newWidth
为新值。
Method m=b.getClass().getMethod(“f”,null)
其中
null
参数可以传一个参数数组
Class[] args=new Class[]{int.class,int.class}
——这里指一个类对象类型的参数数组
.
JAVA
创建类对象的方式:
1.
New
对象
2.
反射
3.
Clone
其中前两种要加构造函数。
下面就动手来做一个简单的ORM框架:
这是一个bean的XML配置文件:
<?
xml version="1.0" encoding="UTF-8"
?>
< xml-body >
< bean id ="item1" class ="test.Item" table ="Item" >
< properties name ="id" type ="Integer" />
< properties name ="name" type ="String" />
< properties name ="description" type ="String" />
< properties name ="price" type ="Double" />
</ bean >
< sql id ="selAll" table ="Item" > select * from Item </ sql >
</ xml-body >
< xml-body >
< bean id ="item1" class ="test.Item" table ="Item" >
< properties name ="id" type ="Integer" />
< properties name ="name" type ="String" />
< properties name ="description" type ="String" />
< properties name ="price" type ="Double" />
</ bean >
< sql id ="selAll" table ="Item" > select * from Item </ sql >
</ xml-body >
下面是建表语句:
CREATE
TABLE
ITEM
(
ID INT PRIMARY KEY IDENTITY ( 0 , 1 ),
NAME VARCHAR ( 20 ),
DESCRIPTION VARCHAR ( 50 ),
PRICE MONEY
)
(
ID INT PRIMARY KEY IDENTITY ( 0 , 1 ),
NAME VARCHAR ( 20 ),
DESCRIPTION VARCHAR ( 50 ),
PRICE MONEY
)
想一下,用户在上面XML配置文件中配置了一个SQL语句,那么他只要传一个ID就可以通过配置文件里面的SQL语句返回一个Bean的集合。具体实现如下:注释我都写在代码中了,自己看吧.
package
test;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class XMLParse ... {
private String tablename;
private String beanname;
private List attrList=new ArrayList();
private int count=0;
public String getTablename() ...{
return tablename;
}
public void setTablename(String tablename) ...{
this.tablename = tablename;
}
//读配置文件<sql>获得sql语句,表名
public String getSql(String sqlId)...{
SAXReader sax=new SAXReader();
Document doc=null;
String strSql=null;
try ...{
doc = sax.read(new File("test/item.xml"));
Element root=doc.getRootElement();
for (Iterator iter = root.elementIterator(); iter.hasNext();) ...{
Element element = (Element) iter.next();
if(element.getName().equalsIgnoreCase("sql") && element.attributeValue("id").equalsIgnoreCase(sqlId))...{
strSql=element.getStringValue();
tablename=element.attributeValue("table");
break;
}
}
} catch (DocumentException e) ...{
// TODO 自动生成 catch 块
e.printStackTrace();
}
return strSql;
}
public static void main(String[] args) ...{
// System.out.println(XMLParse.getSql("selAll"));
}
//根据表名读配置文件获得bean的名字
public String getBeanname(String tablename) ...{
SAXReader sax=new SAXReader();
Document doc=null;
String beanname=null;
try ...{
doc = sax.read(new File("test/item.xml"));
Element root=doc.getRootElement();
for (Iterator iter = root.elementIterator(); iter.hasNext();) ...{
Element element = (Element) iter.next();
if(element.getName().equalsIgnoreCase("bean") && element.attributeValue("table").equalsIgnoreCase(tablename))...{
beanname=element.attributeValue("class");
for(Iterator it=element.elementIterator();it.hasNext();)...{
count++;
Element elepro=(Element) it.next();
String attName=elepro.attributeValue("name");
String attType=elepro.attributeValue("type");
attrList.add(attName+":"+attType);
}
}
}
} catch (DocumentException e) ...{
// TODO 自动生成 catch 块
e.printStackTrace();
}
return beanname;
}
public List getAttrList() ...{
return attrList;
}
public int getCount() ...{
return count;
}
public void setCount(int count) ...{
this.count = count;
}
}
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class XMLParse ... {
private String tablename;
private String beanname;
private List attrList=new ArrayList();
private int count=0;
public String getTablename() ...{
return tablename;
}
public void setTablename(String tablename) ...{
this.tablename = tablename;
}
//读配置文件<sql>获得sql语句,表名
public String getSql(String sqlId)...{
SAXReader sax=new SAXReader();
Document doc=null;
String strSql=null;
try ...{
doc = sax.read(new File("test/item.xml"));
Element root=doc.getRootElement();
for (Iterator iter = root.elementIterator(); iter.hasNext();) ...{
Element element = (Element) iter.next();
if(element.getName().equalsIgnoreCase("sql") && element.attributeValue("id").equalsIgnoreCase(sqlId))...{
strSql=element.getStringValue();
tablename=element.attributeValue("table");
break;
}
}
} catch (DocumentException e) ...{
// TODO 自动生成 catch 块
e.printStackTrace();
}
return strSql;
}
public static void main(String[] args) ...{
// System.out.println(XMLParse.getSql("selAll"));
}
//根据表名读配置文件获得bean的名字
public String getBeanname(String tablename) ...{
SAXReader sax=new SAXReader();
Document doc=null;
String beanname=null;
try ...{
doc = sax.read(new File("test/item.xml"));
Element root=doc.getRootElement();
for (Iterator iter = root.elementIterator(); iter.hasNext();) ...{
Element element = (Element) iter.next();
if(element.getName().equalsIgnoreCase("bean") && element.attributeValue("table").equalsIgnoreCase(tablename))...{
beanname=element.attributeValue("class");
for(Iterator it=element.elementIterator();it.hasNext();)...{
count++;
Element elepro=(Element) it.next();
String attName=elepro.attributeValue("name");
String attType=elepro.attributeValue("type");
attrList.add(attName+":"+attType);
}
}
}
} catch (DocumentException e) ...{
// TODO 自动生成 catch 块
e.printStackTrace();
}
return beanname;
}
public List getAttrList() ...{
return attrList;
}
public int getCount() ...{
return count;
}
public void setCount(int count) ...{
this.count = count;
}
}
package
test;
public class Item ... {
private int id;
private String name;
private String description;
private double price;
public String getDescription() ...{
return description;
}
public void setDescription(String description) ...{
this.description = description;
}
public int getId() ...{
return id;
}
public void setId(int id) ...{
this.id = id;
}
public String getName() ...{
return name;
}
public void setName(String name) ...{
this.name = name;
}
public double getPrice() ...{
return price;
}
public void setPrice(double price) ...{
this.price = price;
}
}
public class Item ... {
private int id;
private String name;
private String description;
private double price;
public String getDescription() ...{
return description;
}
public void setDescription(String description) ...{
this.description = description;
}
public int getId() ...{
return id;
}
public void setId(int id) ...{
this.id = id;
}
public String getName() ...{
return name;
}
public void setName(String name) ...{
this.name = name;
}
public double getPrice() ...{
return price;
}
public void setPrice(double price) ...{
this.price = price;
}
}
package
test;
import java.util. * ;
import java.lang.reflect.Modifier;
import java.sql. * ;
import com.microsoft.jdbc.base.BasePreparedStatement;
public class GetList ... {
public List getRes(String sql) throws Exception...{
List result=new ArrayList();
Connection con=getConnection();
PreparedStatement pstm=con.prepareStatement(sql);
ResultSet rs=pstm.executeQuery();
// System.out.println("dfdfd");
while(rs.next())...{
ResultSetMetaData metadata=rs.getMetaData();
for(int i=1;i<=metadata.getColumnCount();i++)...{
String colname=metadata.getColumnName(i);
Object colvalue=rs.getObject(colname);
int coltype=metadata.getColumnType(i);
result.add(colname+"="+colvalue);
// System.out.println(coltype+":"+metadata.getColumnName(i)+rs.getObject(metadata.getColumnName(i)));
}
}
return result;
}
public Connection getConnection()...{
Connection con=null;
String url="jdbc:microsoft:sqlserver://localhost;DatabaseName=pubs";
try ...{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
con=DriverManager.getConnection(url,"sa","");
} catch (Exception e) ...{
e.printStackTrace();
}
return con;
}
/** *//**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception ...{
GetList list=new GetList();
// list.getRes("select * from item");
// list.Insert();
}
}
import java.util. * ;
import java.lang.reflect.Modifier;
import java.sql. * ;
import com.microsoft.jdbc.base.BasePreparedStatement;
public class GetList ... {
public List getRes(String sql) throws Exception...{
List result=new ArrayList();
Connection con=getConnection();
PreparedStatement pstm=con.prepareStatement(sql);
ResultSet rs=pstm.executeQuery();
// System.out.println("dfdfd");
while(rs.next())...{
ResultSetMetaData metadata=rs.getMetaData();
for(int i=1;i<=metadata.getColumnCount();i++)...{
String colname=metadata.getColumnName(i);
Object colvalue=rs.getObject(colname);
int coltype=metadata.getColumnType(i);
result.add(colname+"="+colvalue);
// System.out.println(coltype+":"+metadata.getColumnName(i)+rs.getObject(metadata.getColumnName(i)));
}
}
return result;
}
public Connection getConnection()...{
Connection con=null;
String url="jdbc:microsoft:sqlserver://localhost;DatabaseName=pubs";
try ...{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
con=DriverManager.getConnection(url,"sa","");
} catch (Exception e) ...{
e.printStackTrace();
}
return con;
}
/** *//**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception ...{
GetList list=new GetList();
// list.getRes("select * from item");
// list.Insert();
}
}
package
test;
import java.lang.reflect. * ;
import java.util. * ;
public class BeanDemo ... {
public List newInstance(String sqlId)...{
//定义一个集合保存bean的实例
List bean=new ArrayList();
try ...{
XMLParse xmlparse=new XMLParse();
GetList gi=new GetList();
//这里是用户在XML文件中配置的sql语句的ID,根据这个ID获得sql语句
String strSql=xmlparse.getSql(sqlId);
String tablename=xmlparse.getTablename();
//这里是通过表名获得bean的名字
String beanname=xmlparse.getBeanname(tablename);
//获得字段的个数
int count=xmlparse.getCount();
//返回bean里面的属性的集合,可以看到是键值对的形式,bean的属性的类型和名字
//然后可以根据类型判断它的具体的类型(太麻烦了就没写了)...
// List attrList=xmlparse.getAttrList();
// String[] strAttrs=new String[attrList.size()];
// for (int i=0;i<attrList.size();i++) {
// String attr = (String) attrList.get(i);
// strAttrs[i]=attr;
// }
// System.out.println(strAttrs[1]);
//根据bean的名字得到类对象
Class obj=Class.forName(beanname);
//定义一个集合保存SQL查询出来的集合
List list=null;
if(strSql!=null)...{
list=gi.getRes(strSql);
}
//定义bean的Object类型的实例,因为这里我们根本就还不知道它里面的属性和方法,要利用
//反射为它赋值
Object item=null;
//遍历结果集
for(int i=0;i<list.size();i++)...{
//根据字段的个数count,每隔count就创建一个新的bean
if(i%count==0)...{
item=obj.newInstance();
}
//获得bean的方法列表
Method[] methods=item.getClass().getMethods();
//注意我们返回的结果集是字段名+值的键值对形式,所以要用sal[]数组来截取
String sqlstr=(String) list.get(i);
String sql[]=sqlstr.split("=");
// for(int k=0;k<strAttrs.length;k++){
// String[] strAttr=strAttrs[i].split(":");
// if(sql[0].equalsIgnoreCase(strAttr[0])){
// if("String".equalsIgnoreCase(strAttr[1])){
// Class[] parm=new Class[]{new String(sql[0]).getClass()};
// item.getClass().getMethod("set"+strAttr[0], parm);
// }
// }
// }
// 这里定义两个变量是保存截取后的set方法,我把set方法截取就可以获得set方法和set的字段
String setstr=null;
String newstr=null;
//遍历未知bean的所有方法以确定哪个set方法为当前的结果集所调用
for(int j=0;j<methods.length;j++)...{
//截取方法:如:setId()截取后变为set和Id,这样就可以判断方法名和字段名
//再去和返回的结果集匹配
setstr=methods[j].getName().substring(0,3);
newstr=methods[j].getName().substring(3);
//判断和结果集字段匹配的set方法
if(setstr.equalsIgnoreCase("set") && newstr.equalsIgnoreCase(sql[0]))...{
// System.out.println(":::");
//不同结果的返回值类型有所不同,这里原来应该对返回的参数的类型进行判断
//后再创建具体的方法参数类型,但太麻烦了所以就直接写的,要是bean里全部定义
//为String类型也OK,就省了判断的那个麻烦的过程了
if(newstr.equalsIgnoreCase("id"))...{
Object[] parm=new Object[]...{new Integer(sql[1])};
//利用反射调用未知bean的set方法为它赋值
methods[j].invoke(item,parm);
// System.out.println("1");
}
if(newstr.equalsIgnoreCase("name"))...{
Object[] parm=new Object[]...{new String(sql[1])};
methods[j].invoke(item,parm);
// System.out.println("2");
}
if(newstr.equalsIgnoreCase("description"))...{
Object[] parm=new Object[]...{new String(sql[1])};
methods[j].invoke(item,parm);
// System.out.println("3");
}
if(newstr.equalsIgnoreCase("price"))...{
Object[] parm=new Object[]...{new Double(sql[1])};
methods[j].invoke(item,parm);
// System.out.println("4");
}
}
}
//根据字段大概每循环count次一个未知bean的赋值工作就完成了,就可以把它保存进集合中了
//注意这时候bean还只是为Object类型,所以未知bean创建好后,就可以直接遍历取出并
//进行转型,就可以直接使用了!
if(i%count==0)...{
bean.add(item);
// System.out.println("11111");
}
// System.out.println(setstr+newstr);
}
} catch (Exception e) ...{
e.printStackTrace();
}
return bean;
}
public void setBean()...{
}
public static void main(String[] args) ...{
BeanDemo bean=new BeanDemo();
List list=bean.newInstance("selAll");
//遍历转型
for (Iterator iter = list.iterator(); iter.hasNext();) ...{
Item it= (Item) iter.next();
System.out.println(it.getId()+" : "+it.getName()+" : "+it.getDescription()+" : "+it.getPrice());
}
}
}
import java.lang.reflect. * ;
import java.util. * ;
public class BeanDemo ... {
public List newInstance(String sqlId)...{
//定义一个集合保存bean的实例
List bean=new ArrayList();
try ...{
XMLParse xmlparse=new XMLParse();
GetList gi=new GetList();
//这里是用户在XML文件中配置的sql语句的ID,根据这个ID获得sql语句
String strSql=xmlparse.getSql(sqlId);
String tablename=xmlparse.getTablename();
//这里是通过表名获得bean的名字
String beanname=xmlparse.getBeanname(tablename);
//获得字段的个数
int count=xmlparse.getCount();
//返回bean里面的属性的集合,可以看到是键值对的形式,bean的属性的类型和名字
//然后可以根据类型判断它的具体的类型(太麻烦了就没写了)...
// List attrList=xmlparse.getAttrList();
// String[] strAttrs=new String[attrList.size()];
// for (int i=0;i<attrList.size();i++) {
// String attr = (String) attrList.get(i);
// strAttrs[i]=attr;
// }
// System.out.println(strAttrs[1]);
//根据bean的名字得到类对象
Class obj=Class.forName(beanname);
//定义一个集合保存SQL查询出来的集合
List list=null;
if(strSql!=null)...{
list=gi.getRes(strSql);
}
//定义bean的Object类型的实例,因为这里我们根本就还不知道它里面的属性和方法,要利用
//反射为它赋值
Object item=null;
//遍历结果集
for(int i=0;i<list.size();i++)...{
//根据字段的个数count,每隔count就创建一个新的bean
if(i%count==0)...{
item=obj.newInstance();
}
//获得bean的方法列表
Method[] methods=item.getClass().getMethods();
//注意我们返回的结果集是字段名+值的键值对形式,所以要用sal[]数组来截取
String sqlstr=(String) list.get(i);
String sql[]=sqlstr.split("=");
// for(int k=0;k<strAttrs.length;k++){
// String[] strAttr=strAttrs[i].split(":");
// if(sql[0].equalsIgnoreCase(strAttr[0])){
// if("String".equalsIgnoreCase(strAttr[1])){
// Class[] parm=new Class[]{new String(sql[0]).getClass()};
// item.getClass().getMethod("set"+strAttr[0], parm);
// }
// }
// }
// 这里定义两个变量是保存截取后的set方法,我把set方法截取就可以获得set方法和set的字段
String setstr=null;
String newstr=null;
//遍历未知bean的所有方法以确定哪个set方法为当前的结果集所调用
for(int j=0;j<methods.length;j++)...{
//截取方法:如:setId()截取后变为set和Id,这样就可以判断方法名和字段名
//再去和返回的结果集匹配
setstr=methods[j].getName().substring(0,3);
newstr=methods[j].getName().substring(3);
//判断和结果集字段匹配的set方法
if(setstr.equalsIgnoreCase("set") && newstr.equalsIgnoreCase(sql[0]))...{
// System.out.println(":::");
//不同结果的返回值类型有所不同,这里原来应该对返回的参数的类型进行判断
//后再创建具体的方法参数类型,但太麻烦了所以就直接写的,要是bean里全部定义
//为String类型也OK,就省了判断的那个麻烦的过程了
if(newstr.equalsIgnoreCase("id"))...{
Object[] parm=new Object[]...{new Integer(sql[1])};
//利用反射调用未知bean的set方法为它赋值
methods[j].invoke(item,parm);
// System.out.println("1");
}
if(newstr.equalsIgnoreCase("name"))...{
Object[] parm=new Object[]...{new String(sql[1])};
methods[j].invoke(item,parm);
// System.out.println("2");
}
if(newstr.equalsIgnoreCase("description"))...{
Object[] parm=new Object[]...{new String(sql[1])};
methods[j].invoke(item,parm);
// System.out.println("3");
}
if(newstr.equalsIgnoreCase("price"))...{
Object[] parm=new Object[]...{new Double(sql[1])};
methods[j].invoke(item,parm);
// System.out.println("4");
}
}
}
//根据字段大概每循环count次一个未知bean的赋值工作就完成了,就可以把它保存进集合中了
//注意这时候bean还只是为Object类型,所以未知bean创建好后,就可以直接遍历取出并
//进行转型,就可以直接使用了!
if(i%count==0)...{
bean.add(item);
// System.out.println("11111");
}
// System.out.println(setstr+newstr);
}
} catch (Exception e) ...{
e.printStackTrace();
}
return bean;
}
public void setBean()...{
}
public static void main(String[] args) ...{
BeanDemo bean=new BeanDemo();
List list=bean.newInstance("selAll");
//遍历转型
for (Iterator iter = list.iterator(); iter.hasNext();) ...{
Item it= (Item) iter.next();
System.out.println(it.getId()+" : "+it.getName()+" : "+it.getDescription()+" : "+it.getPrice());
}
}
}