??xml version="1.0" encoding="utf-8" standalone="yes"?> U别Q?初 刘冬 (winter.lau@163.com), 软g工程? 珠v市创我科技发展有限公司 2003 q?9 ?08 ?/span> JFreeChart是开放源代码站点SourceForge.net上的一个JAVA目Q它主要用来各种各样的图表,q些图表包括Q饼图、柱状图(普通柱状图以及堆栈q?、线图、区域图、分布图、合图、甘特图以及一些A表盘{等。这些不同式L图表基本上可以满目前的要求。ؓ了减篇q本文主要介l前面三U类型的图表Q读者可以触cL通去开发其他样式的图表。下面几个是JFreeChart产生的这三种cd图表的结果: 上面的三个图都是表示四个季度的某个品的销量信息。在l箋下面节之前必须先准备好开发环境,因ؓ是基于WEB览器的图表展现Q因此需要一个Servlet引擎或者是J2EE应用服务器(例如WebSphereQTomcat{)。WEB环境的搭建就不篏赘了Q读者根据喜好自行安装。JFreeChart引擎本n需要到SourceForge.net上下载,地址如下Q? 下蝲的时候需要注意的是必M载两个文ӞJFreeChart以及Jcommon。目前最新配套版本是QJFreeChart 0.9.11 Jcommon 0.8.6 q里有点W者在开发中遇见的问题需要注意的是:在用Eclipse开发的时候会报一个莫名其妙的错误Q错误可能指向某个类文g的第一行。遇到这L问题一般是因ؓ没有把Jcommon的jar包设|到目的类路径中的~故。具体的原因不祥? 在开始用JFreeChart之前我们有必要先大概了解一下JFreeChart本n的结构以及它所带一些例子程序,q样有助于我们下一步自行开发。下载JFreeChart包后已经带有非常丰富的例子,因ؓJFreeChartq个目本n的用文档非常少Q因此学习它最好的办法是学习它所带的例子源码。在包org.jfree.chart.demo中有几十个文件用于展CJFreeChart所能支持的所有图表的l果。如果你的JDK是比较新的情况下可能在运行这些例子时会有问题Q现象如下: q个错误是由于新版的Swing大量的用了微Y的DirectDraw的技术来提高d的性能Q而可能你的显卡在q时候会跟你闹点情A或者显卡本wƈ不支持这L一个技术。难道就没有办法了嘛Q要解决q个问题也非常简单,我们可以屏蔽掉DirectDrawQ不让Swing使用该技术就可以了。在q行q些代码时给虚拟机指定参?Dsun.java2d.noddraw卛_? q时可能你又该纳闷了Q不说是ZWeb的图表嘛Q怎么又扯到Swing上了Q这是因Zؓ了开发者容易上手,无需配置Mq行环境Q所以这些例子都是基于GUI方式的用于展现给开发者如果生成一个图表,我们要学习的也就是如何利用这个引擎生成图表而不是怎么来显CZ个图表。当我们把生成的图表对象ExportC个图像文件即可在Web上发布? 下面我们来介lJFreeChart中几个核心的对象c: 基本上我认ؓJFreeChart目本n的类l构的设计ƈ不是很好Q首先在创徏图表的时候用C大量的工厂方法,q样做虽然可以简化创建图表对象的代码Q但是对目本n或者开发h员来讲自行扩展一U新的图表都仍然是一件很ȝ的事情;其次除图表对象本w外其余的类q于复杂Q用者必d了解每个cd的图表对象应该对应哪些Axis、Plot、Rendererc,q且必须非常熟悉q些cȝ构造函C每个参数的具体含义。这些问题都大大困扰很多初学者。不q,虽然存在很多问题Q但是JFreeChart本n仍不׃ؓ一个非怼U的图表引擎,况且目本n也在逐渐的发展中? 在非常简略的介绍了JFreeChart本n的代码结构后Q下面我们开始动手试验几个常用的图表q把他们攑ֈweb上? 限于幅的问题我们在q里只实CU常用的图表Q其他类型图表读者可以触cL通。我们先l出q囄实现Q饼囄实现再来跟柱状图q行比较?
E序q行l束后生成的囄文g效果如下图所C: 如果是用简单的数据即用getDataSetҎ获取数据集时产生的图片文件如下:
对于饼图而言Q数据集的获取用的不是同一个数据集c,另外饼图不支持同一个类别的目中还有子目q样的数据。我们只l出创徏饼图的代码,至于写图表到一个文件则与柱状图一_无需重复? 生成的饼图文件效果如下: Z生成的图表直接传给客户端浏览器Q只需要将前面两个例子中的文g换成是通过HttpServletResponse对象获取到的输出,详细代码清单如下Q? 很多情况我们不仅仅要求可以在览器上昄一个图表,我们更需要客户可以直接在图表上做一下交互的操作Q例如获取信息提C,点击图表某个部分q行更详l信息的展示{等。例如前面生成的单柱状图Q用户需要在看到q囑点击某种水果例如是苹果即可看到各个地果量的情况。ؓ此就要求该图形具有交互操作的功能。在HTML中ؓ了让一个图像具有可交互的功能就必须l该囑փ定义一个Map对象。下表节选一D具有该功能的HTML代码 由此׃生了一个问题:如果Ҏ一个图像来生成对应的MAP对象。我们回头看看刚才的代码Q在创徏一个图表对象时候有两个参数Q我们Dq囄例子来讲q两个参数就是ChartFactory. createBarChart3DҎ中的最后两个参敎ͼq两个参数的cd都是布尔倹{这两个参数意思分别是Q是否创建工hC?tooltip)以及是否生成URL。这两个参数分别对应着MAP中一个AREA的title属性以及href属性? 可是我想知道的是怎么来生这个MAP啊!哈哈Q不要着急,JFreeChart已经帮我们做好生成MAP对象的功能。ؓ了生成MAP对象p引入另外一个对象:ChartRenderingInfo。因为JFreeChart没有直接的方法利用一个图表对象直接生成MAP数据Q它需要一个中间对象来q渡Q这个对象就是ChartRenderingInfo。下图是生成MAP数据的流E图Q? 如上图所C,ChartUtilitiescL整个程的核心,它周围的对象都是一些例如数据对象或者是文g{。这个流E简单描q如下:首先创徏一个ChartRenderingInfo对象q在调用ChartUtilities的writeChartAsJPEG时作为最后一个参C递进厅R调用该Ҏl束后将产生一个图像文件以及一个填充好MAP数据的ChartRenderingInfo对象Q有了这个对象我们还是没有办法获取具体的MAP数据Q我们还必须借助于ChartUtilities的writeImageMapҎ来将ChartRenderingInfo对象d出来Q获取MAP数据的代码片断如下: 打开文gD:\fruit.mapQ文件的内容是要写到页面上的MAP数据。把生成的图像文件以及MAP数据文g写到面上即可完成热点图表的功能。至于怎么l合两者之间的关系例如囑փ的useMap属性值必MMAP对象的名U结合v来,必须Ҏ实际的应用情况进行相应的处理。笔者徏议把二者通过标签库封装v来,囑փ文g的名UC及MAP对象的名U由标签库统一q行控制Q这样可以保证二者的一致性?
使用 JFreeChart来创建基于web的图?/span>
文档选项
WWW的发展得基于因特网的应用程序不再局限于静态或者简单的动态内Ҏ供。传l的一些以软g包Ş式发布应用程序例如报表系l等都在逐渐搬到因特|上。但是这两者之间有着天壤之别Q虽然对于数据获取、业务处理等斚w基本cMQ但是最大的差别在于用户界面。ؓ了能在web览器上昄要求用户界面使用HTML以及囄的方式来展现数据Q而传l的一些利用操作系l本w的控g来开发的用户界面无法适应琳琅满目的客LQ因此在q里也变得无能ؓ力。回到本文的题目上来Qؓ了创Z个可以在web览器上查看到图表一般有两种做法Q第一U就是用applet利用java本n对图形的支持来显CZ个图表;W二U就是直接在web服务器端生成好图表图片文件后发送给览器。第一U方式显然对于客L要求太高Q随着现在L览器放弃对JAVA的支持后Q这U方式只适合一些局域网的应用,而对于因特网的环境就昑־不太适合。因此我们下面将介绍一个JAVA的图表引擎JFreeChart用来产生ZWEB的图表?/span>
?
?
?
JFreeChart主页Q?
http://www.jfree.org/jfreechart/index.html
JFreeChart下蝲面Q?
http://sourceforge.net/projects/jfreechart/
回页?/span>
java.lang.UnsatisfiedLinkError: initDDraw
at sun.awt.windows.Win32OffScreenSurfaceData.initDDraw(Native Method)
at sun.awt.windows.Win32OffScreenSurfaceData.<clinit>(Win32OffScreenSurfaceData.java:141)
at sun.awt.Win32GraphicsDevice.<clinit>(Win32GraphicsDevice.java:58)
at sun.awt.Win32GraphicsEnvironment.makeScreenDevice(Win32GraphicsEnvironment.java:168)
at sun.java2d.SunGraphicsEnvironment.getScreenDevices(SunGraphicsEnvironment.java:240)
at sun.awt.Win32GraphicsEnvironment.getDefaultScreenDevice(Win32GraphicsEnvironment.java:61)
at java.awt.Window.init(Window.java:224)
at java.awt.Window.<init>(Window.java:268)
at java.awt.Frame.<init>(Frame.java:398)
at javax.swing.JFrame.<init>(JFrame.java:198)
at org.jfree.chart.demo.JFreeChartDemo.<init>(JFreeChartDemo.java:148)
at org.jfree.chart.demo.JFreeChartDemo.main(JFreeChartDemo.java:285)
Exception in thread "main"
cd
cȝ作用以及单描q?/span>
JFreeChart
图表对象QQ何类型的图表的最l表现Ş式都是在该对象进行一些属性的定制。JFreeChart引擎本n提供了一个工厂类用于创徏不同cd的图表对?/span>
XXXXXDataset
数据集对象,用于提供昄图表所用的数据。根据不同类型的图表对应着很多cd的数据集对象c?/span>
XXXXXPlot
图表区域对象Q基本上q个对象军_着什么样式的图表Q创对象的时候需要Axis、Renderer以及数据集对象的支持
XXXXXAxis
用于处理图表的两个uQ纵轴和横u
XXXXXRenderer
负责如何昄一个图表对?/span>
XXXXXURLGenerator
用于生成Web图表中每个项目的鼠标点击链接
XXXXXToolTipGenerator
用于生成图象的帮助提C,不同cd图表对应不同cd的工hC类
回页?/span>
package lius.chart.demo;
import java.io.*;
import org.jfree.data.*;
import org.jfree.chart.*;
import org.jfree.chart.plot.*;
/**
* 该类用于演示最单的q囄?
* @author Winter Lau
*/
public class BarChartDemo {
public static void main(String[] args) throws IOException{
CategoryDataset dataset = getDataSet2();
JFreeChart chart = ChartFactory.createBarChart3D(
"水果产量?, // 图表标题
"水果", // 目录轴的昄标签
"产量", // 数Du的显C标{?
dataset, // 数据?
PlotOrientation.VERTICAL, // 图表方向Q水q뀁垂?
true, // 是否昄图例(对于单的q囑ֿLfalse)
false, // 是否生成工具
false // 是否生成URL链接
);
FileOutputStream fos_jpg = null;
try {
fos_jpg = new FileOutputStream("D:\\fruit.jpg");
ChartUtilities.writeChartAsJPEG(fos_jpg,100,chart,400,300,null);
} finally {
try {
fos_jpg.close();
} catch (Exception e) {}
}
}
/**
* 获取一个演C用的简单数据集对象
* @return
*/
private static CategoryDataset getDataSet() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(100, null, "Ҏ");
dataset.addValue(200, null, "梨子");
dataset.addValue(300, null, "葡萄");
dataset.addValue(400, null, "香蕉");
dataset.addValue(500, null, "荔枝");
return dataset;
}
/**
* 获取一个演C用的组合数据集对象
* @return
*/
private static CategoryDataset getDataSet2() {
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(100, "北京", "Ҏ");
dataset.addValue(100, "上v", "Ҏ");
dataset.addValue(100, "q州", "Ҏ");
dataset.addValue(200, "北京", "梨子");
dataset.addValue(200, "上v", "梨子");
dataset.addValue(200, "q州", "梨子");
dataset.addValue(300, "北京", "葡萄");
dataset.addValue(300, "上v", "葡萄");
dataset.addValue(300, "q州", "葡萄");
dataset.addValue(400, "北京", "香蕉");
dataset.addValue(400, "上v", "香蕉");
dataset.addValue(400, "q州", "香蕉");
dataset.addValue(500, "北京", "荔枝");
dataset.addValue(500, "上v", "荔枝");
dataset.addValue(500, "q州", "荔枝");
return dataset;
}
}
?
?
package lius.chart.demo;
import java.io.*;
import org.jfree.data.*;
import org.jfree.chart.*;
/**
* 用于演示饼图的生?
* @author Winter Lau
*/
public class PieChartDemo {
public static void main(String[] args) throws IOException{
DefaultPieDataset data = getDataSet();
JFreeChart chart = ChartFactory.createPie3DChart("水果产量?, // 图表标题
data,
true, // 是否昄图例
false,
false
);
//写图表对象到文gQ参照柱状图生成源码
}
/**
* 获取一个演C用的简单数据集对象
* @return
*/
private static DefaultPieDataset getDataSet() {
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("Ҏ",100);
dataset.setValue("梨子",200);
dataset.setValue("葡萄",300);
dataset.setValue("香蕉",400);
dataset.setValue("荔枝",500);
return dataset;
}
}
?
回页?/span>
package lius.chart.demo;
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import org.jfree.data.*;
import org.jfree.chart.*;
/**
* 演示通过servlet直接输出图表
* @author Winter Lau
*/
public class ChartDemoServlet extends HttpServlet {
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
res.setContentType("image/jpeg");
DefaultPieDataset data = getDataSet();
JFreeChart chart = ChartFactory.createPie3DChart("水果产量?,
data,
true,
false,
false
);
ChartUtilities.writeChartAsJPEG(res.getOutputStream(),
100,chart,400,300,null);
}
/**
* 获取一个演C用的简单数据集对象
* @return
*/
private static DefaultPieDataset getDataSet() {
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("Ҏ",100);
dataset.setValue("梨子",200);
dataset.setValue("葡萄",300);
dataset.setValue("香蕉",400);
dataset.setValue("荔枝",500);
return dataset;
}
}
回页?/span>
<MAP NAME="chartMap">
<AREA SHAPE="RECT" COORDS="81,15,126,254" href="?series=0&category=100" title="100 = 7,048"
onclick="javascript:clickChart('100');return false;">
<AREA SHAPE="RECT" COORDS="143,27,188,255" href="?series=0&category=200" title="200 = 6,721"
onclick="javascript: clickChart ('200');return false;">
<AREA SHAPE="RECT" COORDS="205,54,250,255" href="?series=0&category=300" title="300 = 5,929"
onclick="javascript: clickChart ('300');return false;">
<AREA SHAPE="RECT" COORDS="267,85,312,255" href="?series=0&category=400" title="400 = 5,005"
onclick="javascript: clickChart ('400');return false;">
<AREA SHAPE="RECT" COORDS="329,17,374,255" href="?series=0&category=Diet" title="Diet = 7,017" onclick="javascript:
clickChart ('Diet');return false;">
</MAP>
?
PrintWriter w = null;
FileOutputStream fos_jpg = null;
FileOutputStream fos_cri = null;
try{
//Ҏ不同cd的图表用不同类Q以下是针对饼图的操?
PiePlot plot = (PiePlot) chart.getPlot();
plot.setURLGenerator(new StandardPieURLGenerator(url));
//讄工具提示
plot.setToolTipGenerator(new StandardPieToolTipGenerator());
fos_jpg = new FileOutputStream(“d:\\fruit.jpg”);
ChartUtilities.writeChartAsJPEG(
fos_jpg,
100,
chart,
400,
300,
info);
fos_cri = new FileOutputStream(__d:\\fruit.map__);
w = new PrintWriter(fos_cri);
ChartUtilities.writeImageMap(w, __mapname__, info);
w.flush();
}finally{
try{
w.close();
}catch(Exception e){}
try{
fos_cri.close();
}catch(Exception e){}
try{
fos_jpg.close();
}catch(Exception e){}
}
]]>
[关键字] JAVA JDK 枚D
1Q它不能有public的构造函敎ͼq样做可以保证客户代码没有办法新Z个enum的实例?
2Q所有枚丑ր都是public , static , final的。注意这一点只是针对于枚D|我们可以和在普通类里面定义 变量一样定义其它Q何类型的非枚丑֏量,q些变量可以用Q何你想用的修饰符?
3QEnum默认实现了java.lang.Comparable接口?
4QEnum覆蝲了了toStringҎQ因此我们如果调用Color.Blue.toString()默认q回字符?#8221;Blue”.
5QEnum提供了一个valueOfҎQ这个方法和toStringҎ是相对应的。调用valueOf(“Blue”)返回Color.Blue.因此我们在自己重写toStringҎ的时候就要注意到q一点,一把来说应该相对应地重写valueOfҎ?
6QEnumq提供了valuesҎQ这个方法你能够方便的遍历所有的枚D倹{?
7QEnumq有一个oridinal的方法,q个Ҏq回枚D值在枚Dcȝ的顺序,q个序Ҏ枚D值声明的序而定Q这里Color.Red.ordinal()q回0?
了解了这些基本特性,我们来看看如何用它们?
1Q遍历所有有枚D? 知道了有valuesҎQ我们可以轻车熟路地用ForEach循环来遍历了枚Dg?
for (Color c: Color.values())
System.out.println(“find value:” + c);
2Q在enum中定义方法和变量Q比如我们可以ؓColor增加一个方法随回一个颜艌Ӏ?
public enum Color {
Red,
Green,
Blue;
/*
*定义一个变量表C枚丑ր的数目?
*(我有点奇怪ؓ什么sun没有lenum直接提供一个sizeҎ).
*/
private static int number = Color.values().length ;
/**
* 随机q回一个枚丑ր?
@return a random enum value.
*/
public static Color getRandomColor(){
long random = System.currentTimeMillis() % number;
switch ((int) random){
case 0:
return Color.Red;
case 1:
return Color.Green;
case 2:
return Color.Blue;
default : return Color.Red;
}
}
}
可以看出q在枚Dcd里定义变量和Ҏ和在普通类里面定义Ҏ和变量没有什么区别。唯一要注意的只是变量和方法定义必L在所有枚丑ր定义的后面Q否则编译器会给Z个错误?
3Q覆?Override)toString, valueOfҎ
前面我们已经知道enum提供了toString,valueOf{方法,很多时候我们都需要覆载默认的toStringҎQ那么对于enum我们怎么做呢。其实这和覆载一个普通class的toStringҎ没有什么区别?
….
public String toString(){
switch (this){
case Red:
return "Color.Red";
case Green:
return "Color.Green";
case Blue:
return "Color.Blue";
default:
return "Unknow Color";
}
}
….
q时我们可以看到Q此时再用前面的遍历代码打印出来的是
Color.Red
Color.Green
Color.Blue
而不?
Red
Green
Blue.
可以看到toString实是被覆蝲了。一般来说在覆蝲toString的时候我们同时也应该覆蝲valueOfҎQ以保持它们怺的一致性?
4Q用构造函?
虽然enum不可以有public的构造函敎ͼ但是我们q是可以定义private的构造函敎ͼ在enum内部使用。还是用Colorq个例子?
public enum Color {
Red("This is Red"),
Green("This is Green"),
Blue("This is Blue");
private String desc;
Color(String desc){
this.desc = desc;
}
public String getDesc(){
return this.desc;
}
}
q里我们为每一个颜色提供了一个说明信? 然后定义了一个构造函数接受这个说明信息?
要注意这里构造函C能ؓpublic或者protected, 从而保证构造函数只能在内部使用Q客户代码不能new一个枚丑ր的实例出来。这也是完全W合情理的,因ؓ我们知道枚D值是public static final的常量而已?
5Q实现特定的接口
我们已经知道enum可以定义变量和方法,它要实现一个接口也和普通class实现一个接口一Pq里׃作示例了?
6Q定义枚丑րDqҎ?
前面我们看到可以为enum定义一些方法,其实我们甚至可以为每一个枚丑ր定义方法。这P我们前面覆蝲 toString的例子可以被改写成这栗?
public enum Color {
Red {
public String toString(){
return "Color.Red";
}
},
Green {
public String toString(){
return "Color.Green";
}
},
Blue{
public String toString(){
return "Color.Blue";
}
};
}
从逻辑上来说这h原先提供一?#8220;全局“的toStringҎ要清C些?
ȝ来说Qenum作ؓ一个全新定义的cdQ是希望能够帮助E序员写出的代码更加单易懂,个h觉得一般也不需要过多的使用enum的一些高U特性,否则和单易懂的初衷惌背了?/span>
]]>
[关键字] JAVA 反射机制
JAVA反射机制是在q行状态中Q对于Q意一个类Q都能够知道q个cȝ所有属性和ҎQ对于Q意一个对象,都能够调用它的Q意一个方法;q种动态获取的信息以及动态调用对象的Ҏ的功能称为java语言的反机制?
Java反射机制主要提供了以下功能: 在运行时判断L一个对象所属的c;在运行时构造Q意一个类的对象;在运行时判断L一个类所h的成员变量和ҎQ在q行时调用Q意一个对象的ҎQ生成动态代理?
1. 得到某个对象的属?
1 public Object getProperty(Object owner, String fieldName) throws Exception {
2 Class ownerClass = owner.getClass();
3
4 Field field = ownerClass.getField(fieldName);
5
6 Object property = field.get(owner);
7
8 return property;
9 }
Class ownerClass = owner.getClass()Q得到该对象的Class?
Field field = ownerClass.getField(fieldName)Q通过Class得到cd明的属性?
Object property = field.get(owner)Q通过对象得到该属性的实例Q如果这个属性是非公有的Q这里会报IllegalAccessException?
2. 得到某个cȝ静态属?
1 public Object getStaticProperty(String className, String fieldName)
2 throws Exception {
3 Class ownerClass = Class.forName(className);
4
5 Field field = ownerClass.getField(fieldName);
6
7 Object property = field.get(ownerClass);
8
9 return property;
10 }
Class ownerClass = Class.forName(className) Q首先得到这个类的Class?
Field field = ownerClass.getField(fieldName)Q和上面一P通过Class得到cd明的属性?
Object property = field.get(ownerClass) Q这里和上面有些不同Q因属性是静态的Q所以直接从cȝClass里取?
3. 执行某对象的Ҏ
1 public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {
2
3 Class ownerClass = owner.getClass();
4
5 Class[] argsClass = new Class[args.length];
6
7 for (int i = 0, j = args.length; i < j; i++) {
8 argsClass[i] = args[i].getClass();
9 }
10
11 Method method = ownerClass.getMethod(methodName, argsClass);
12
13 return method.invoke(owner, args);
14 }
Class owner_class = owner.getClass() Q首先还是必d到这个对象的Class?
5?行:配置参数的Class数组Q作为寻找Method的条件?
Method method = ownerClass.getMethod(methodName, argsClass)Q通过Method名和参数的Class数组得到要执行的Method?
method.invoke(owner, args)Q执行该MethodQinvokeҎ的参数是执行q个Ҏ的对象,和参数数l。返回值是ObjectQ也既是该方法的q回倹{?
4. 执行某个cȝ静态方?
1 public Object invokeStaticMethod(String className, String methodName,
2 Object[] args) throws Exception {
3 Class ownerClass = Class.forName(className);
4
5 Class[] argsClass = new Class[args.length];
6
7 for (int i = 0, j = args.length; i < j; i++) {
8 argsClass[i] = args[i].getClass();
9 }
10
11 Method method = ownerClass.getMethod(methodName, argsClass);
12
13 return method.invoke(null, args);
14 }
基本的原理和实例3相同Q不同点是最后一行,invoke的一个参数是nullQ因是静态方法,不需要借助实例q行?
5. 新徏实例
1
2 public Object newInstance(String className, Object[] args) throws Exception {
3 Class newoneClass = Class.forName(className);
4
5 Class[] argsClass = new Class[args.length];
6
7 for (int i = 0, j = args.length; i < j; i++) {
8 argsClass[i] = args[i].getClass();
9 }
10
11 Constructor cons = newoneClass.getConstructor(argsClass);
12
13 return cons.newInstance(args);
14
15 }
q里说的Ҏ是执行带参数的构造函数来新徏实例的方法。如果不需要参敎ͼ可以直接使用newoneClass.newInstance()来实现?
Class newoneClass = Class.forName(className)Q第一步,得到要构造的实例的Class?
W?~第9行:得到参数的Class数组?
Constructor cons = newoneClass.getConstructor(argsClass)Q得到构造子?
cons.newInstance(args)Q新建实例?
6. 判断是否为某个类的实?
1 public boolean isInstance(Object obj, Class cls) {
2 return cls.isInstance(obj);
3 }
7. 得到数组中的某个元素
1 public Object getByArray(Object array, int index) {
2 return Array.get(array,index);
3 }
]]>
]]>
1、徏立一个类Q包括一个格式将中文转换为ISO8859-1~码的方法:
publicclass Format2Chinese {
public Format2Chinese() {
}
public String format2IS08859(String str) {
try {
if (str == null str.trim().equals(""))
str = "";
else
str = new String(str.getBytes("ISO8859-1"));
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
}
2、你的bean里面q时p加一些东西了Q如下面q个单的bean:
publicclass Leavemsg
{
public Leavemsg() {
]]>
package java.lang;
public class Test {
public static void main(String[] args) {
char[] c = "1234567890".toCharArray();
String s = new String(0, 10, c);
}
}
StringcL一个Package权限的构造函数String(int offset, int length, char[] array)Q按照默认的讉K权限Q由于Test属于java.lang包,因此理论上应该可以访问String的这个构造函数。编译通过Q执行时l果如下Q?
Exception in thread "main" java.lang.SecurityException: Prohibited package name:
java.lang
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClassInternal(Unknown Source)
奇怪吧Q要弄清Z么会有SecurityExceptionQ就必须搞清楚ClassLoader的机制?
Java的ClassLoader是用来动态装载class的,ClassLoader对一个class只会装蝲一ơ,JVM使用的ClassLoader一共有4U:
启动c装载器Q标准扩展类装蝲器,c\径装载器和网l类装蝲器?
q?UClassLoader的优先依次从高CQ用所谓的“双亲委派模型”。确切地_如果一个网l类装蝲器被h装蝲一个java.lang.IntegerQ它会首先把h发送给上一U的c\径装载器Q如果返回已装蝲Q则|络c装载器不会装载这个java.lang.IntegerQ如果上一U的c\径装载器q回未装载,它才会装载java.lang.Integer?
cM的,c\径装载器收到h后(无论是直接请求装载还是下一U的ClassLoader上传的请求)Q它也会先把h发送到上一U的标准扩展c装载器Q这样一层一层上传,于是启动c装载器优先U最高,如果它按照自q方式扑ֈ了java.lang.IntegerQ则下面的ClassLoader 都不能再装蝲java.lang.IntegerQ尽你自己写了一个java.lang.IntegerQ试囑֏代核心库的java.lang.Integer是不可能的,因ؓ自己写的q个cL本无法被下层的ClassLoader装蝲?
再说说Package权限。Java语言规定Q在同一个包中的classQ如果没有修饰符Q默认ؓPackage权限Q包内的class都可以访问。但是这q不够准。确切的_只有由同一个ClassLoader装蝲的class才具有以上的Package权限。比如启动类装蝲器装载了java.lang.StringQ类路径装蝲器装载了我们自己写的java.lang.TestQ它们不能互相访问对方具有Package权限的方法。这样就L了恶意代码访问核心类的Package权限Ҏ?/span>
]]>