文档库 最新最全的文档下载
当前位置:文档库 › Java类装载机制的研究及应用

Java类装载机制的研究及应用

Java类装载机制的研究及应用
Java类装载机制的研究及应用

信息科学

Java类装载机制的研究及应用

周洪照耿祥义

(大连交通大学,辽宁大连116028)

引言

随着网络的普及,以网络为核心的硬件环境所包含的硬件设备的广泛性和多样性以及由此带来的软件的安全性、程序的健壮性和可迁移性逐渐成为软件开发者必须面对的挑战。继c和c++之后成为商业软件主流的开发语言java所具有的平台无关性、安全性和网络移动性则很好的帮助软件开发者面对挑战抓住机遇。而java语言面向网络的的核心就是java虚拟机——

—所有的java程序都在其上面运行。深入了解java虚拟机则成为每个java开发人员得心应手的使用java语言的必要前提。所有的这一切就要从java的类装载机制开始。

1java虚拟机的体系结构

Java虚拟机的内部基本结构如图1所示

当虚拟机要执行一个程序时必须首先获得该程序的字节码。每个虚拟机都有一个类装载子系统,他根据给定的全限命名来装入指定的类或接口,然后由执行引擎执行包含在被装载类的方法中的指令。

2类装载子系统

Java虚拟机有两种类装载器:启动类装载器和用户自定义的装载器[1]。java类型要么由启动类装载器装载,要么由用户自定义的类装载器装载。

启动类装载器:每个java虚拟机实现都必须有一个启动类装载器,只要给定某个类型的全限命名,启动类加载器就必须能够以某种方式得到定义该类型的数据。图2中的bootstrap就是启动类加载器,它在虚拟机启动后负责加载核心javaAPI类。

用户自定义加载器:这种装载器能够使用自定义的方式来装载类,类装载子系统中除了boot-strap类加载器之外的都是用户自定义的类加载器,包括standardExt和system类加载器。其中standardExt负责加载java扩展类(¥JA-

VA_HOME/jre/lib/ext目录中的所有

类),system负责加载ClassPath中设置

的路径的类,它是默认的类加载器,一般

用户应用程序的类都由此加载器负责加

载。所有用户自定义加载器都必须继承

java.lang.ClassLoader类,通过调用用户

自定义加载器的laodClass方法来加载

java类。

3类装载器的装载模式和过程

3.1装载模式。java类加载模式称

为双亲委派加载模式,当一个类加载器被要求加

载某个类时,它先委托它的父加载器加载这个类,

父加载器再委托它的父加载器加载这个类,直到

某个加载器能够加载或者已经加载了这个类为

止。如果一直到根加载

器都不能加载这个类,

则逐级返回,由最初的

加载器尝试加载。每个

java类只能由一个加载

器加载。

3.2装载过程。在运

行java.exe时,java.exe首

先找到虚拟机运行环境

JRE中的jvm.dll文件,

启动虚拟机

由bootstrap类加载

器加载核心javaAPI类,

standardExt类加载器加

载¥JAVA_HOME/jre/lib

/ext下的所有jar包,再

由system类加载器加载

由系统参数java.class.

path得到的类的搜索路

径。

包含main()的入口类由system的laodclass()

方法载入。

由New关键字创建的某个类的一个实例,该

类由包含new语句类的类装载器的loadclass方法

载入。

下面我们看一段简单的程序来说明加载的

顺序:

PublicclassTestClass{

Publicstaticvoidmain(String[]args){

Stringstr=newString("hello");

Integer.toString(5);

……

Testtest=newTest();

……

上面的一段简单的代码再执行的时候,系统

地启动加载器bootstrap首先加载java核心

API类,standerExt加载¥JAVA_HOME/jre/li

b/ext下面的jar包,而包含main方法的TestClass

类则由system类加载器加载。当运行到Stringstr

=newString("hello");时,system加载器委托

standerExt加载器加载类String,standerExt加载器

委托bootstrap类加载器加载,而此时bootstrap类

加载器发现已经加载过String类,程序向下运行,

Tnteger类的加载过程也类似。当加载器要加载

Test类时,standerExt类加载器和bootstrap加载器

都无法加载,则由TestClass类所在的system类加

载器负责加载,如果Test类存放在system类加载

器的系统参数java.class.path得到的搜索路径的目

录下面时,则由system类加载器就加载Test类,

如果不在,则Test类就无法加载,此时程序运行抛

出异常。

3.3加载方式。类的加载方式可分为两种显式

加载和隐式加载[2]

显式加载:通过class的forName方法来加

载,相当于

this.getClass(XXX).getClassLoader.loadClass

(XXX,true);如

ClassdoubleClass=Class.forName("java.

lang.Double");

隐式加载:相当于使用当前正在执行的类的

加载器来加载类,默认情况下,所有的java程序的

类都是通过system类加载器加载的。

3.4用户自定义类加载器的工作流程。编写用

户自定义类加载器之需要重载findClass方法即

可。具体流程图如图3所示。

4类加载器的简单应用示例

用户自定义的加载器使类的加载和实例化

可以放到运行时决定,能够实现在线加载、再现升

级的功能,同时可以扩展class文件的来源,使

bootstrap_system层次的ClassLoader不仅仅能存

取本地的class文件,同时可以从网络、数据库等

处获得class文件。下面给出一个简单的运用类的

装载机制实现的在线升级的示例:

publicInterfaceI{

Stringexec(Stringarg);

PublicAimplementsI{

摘要:java语言是一种动态解释性编程语言,它与c和c++编译后生成一个可执行文件不同,java编译后只生成一个个的字节码。class文件,而在运行时按需求和一定的规则载入内存。介绍了java类的装载机制,并通过一个简单的在线升级程序示例说明装载机制的应用。

关键词:java虚拟机;装载机制;在线升级

图2

图3

(下转152页)

文化教育

Stringexec(Stringarg){

Return"hello"+arg;

publicUserClassLoaderextendsClassLoader{…};

//在线升级

PublicClassServiceManager{

Iai;

Publicinit(){

UserClassLoaderuserCL=newUser-ClassLoader();

ClassaClass=userCL.loadClass("A");

Ai=(I)aClass.newInstance();//现在可以调用ai处理业务逻辑

//启动检测线程,检查A.class文件的变化

}//检测线程一旦发现A.class文件发生变化,则调用如下代码

/*

UserClassLoaderuserCl=newUserClass-Loader();

ClassaClass.newInstance();

*/

5小结

了解java类的装载机制,有助于我们更深一步的学习java这门技术,更熟练的掌握java编程技巧和内部运行机制,有助于提高程序的运行效率和质量。

参考文献

[1]BillVenners.深入java虚拟机.曹晓刚,蒋靖译.[M].北京:机械工业出版社,2003,9.

[2]黄明,刘阳.java虚拟机加载机制浅析[J].科技咨询导报,2007,9.

刍议语文教学中学生创新意识的培养

黎峰

(江苏省无锡市苏南技术学校,江苏无锡214073)

1更新教师观念,树立创新性教学意识

教师要加强新课改理论的学习,在实际工作中,大胆探索,勇于实践,不断转变教育观念,树立“一切为了孩子,为了孩子一切,为了一切孩子”的新理念,是培养学生创新意识的前提条件。具体地说,培养学生的创新意识,教师必须具备以下观念:

1.1素质观。素质教育是大势所趋,势在必行。语文素质的核心是语文创新能力,语文创新能力强是语文素质高的重要标志。可以这么说,没有语文创新能力,就没有真正意义上的语文素质,因为具有创新能力的语文素质,才具有极强的生命力和巨大的爆发力。所以,语文课堂必须肩负起历史赋予的重任,着力培养以创新能力为核心的语文素质。

1.2人本观。只有树立了以人为本的观念,才能开发学生的创新智力,发展他们的创新思维,培养他们的创新表达;才能不为应试教育所左右,不为琐碎练习所束缚,不被满堂灌所淹没,才能使学生产生创新智慧,迸发创新火花,获得创新见识。

1.3主体观。没有学生的创新,就没有语文课堂的创新,后者是依靠前者的存在而存在,随着前者的发展而发展的,所以要想语文课堂教学创新,就必须树立学生是主体的观点。因为如果没有主体观点,学生就成不了主人,那绝不会有什么创新可言。

1.4民主观。教育要民主,教学更需要民主。只有在和谐的环境里,学生才能够畅所欲言,大胆创新,提出独到见解。试想,如果教师一发话,如同下了圣旨,还有学生的百花齐放,百家争鸣吗?学生不能“放”,不能“鸣”,何来语文课堂教学的创新?

2改革课堂结构,培养学生的创新意识

教师具备了创新理念,要培养学生的创新意识,还必须改革课堂结构,必须改革现有的课堂教学模式,让学生主动地参与到教学之中去,真正成为学习的主人。

首先,要把教师的“教”转变为学生的“学”,创造一种适合每个学生生动活泼,主动发展的教学氛围,让学生体验到主动获取知识的乐趣,体验在主动参与学习的过程中获得成功的喜悦。语文教学中,我采用“自学——

—讨论交流——

—启发指导——

—练习迁移”这一教学模式来培养学生的创新意识和创新能力。

其次,把“应试”训练转变为应用所学的知识去解决实际问题能力的训练。学生应在教师的启发和引导下,应用所学的知识,去探索发现问题和解决问题的方法,努力做到举一反三,触类旁通的目的。语文课堂应给学生以无限的空间,让畅想的思维自由飞翔,每节课都应有真情的交融,高峰的体验,心潮的激荡,灵感的爆发。教师要为学生的创新训练创造条件,提供机会,让学生自己选择

或设计训练题,去探索解决问题的途径与方法,使

学生的形象思维和创造思维同时得到发展。

第三,把传统的教学专制现象转变为教学

民主化措施。实现教学民主化是将教师的“教”和

学生的“学”成为一种课堂互动,彼此交流的过

程,让教学在活跃,和谐的气氛中人人参与,平等

对话,互相学习的过程中进行,使师生在人格上

处于平等地位,让学生真正成为有血有肉,有创新

能力的学习主人。教师要对好质疑,好提出“怪”

问题,提出超越教材范围的问题的学生,给予鼓励

和引导,持热情支持的态度。这样做不仅使学生

的人格和自尊心得到保护,同时他们的智力和潜

能才能得到开发,创新意识才能得到培养和提

高。

3通过创设问题情景,培养学生的创新意识

学会创设问题情景,是培养学生创新意识的

重要途径之一。问题是创造之源,疑问是创造之

母。培养学生的创新意识,首先就要从培养和解

决学生的问题意识开始。这就要求教师深入钻研

教材,了解学生,确定教学目标,设计出把教学目

标转化为学习行为目标的问题。其次,充分发挥

学生合作学习的功能。对于问题的答案或处理意

见有分歧时,教师要利用小组合作学习的形式,

在合作中,通过师生交流,辩论,生生交流,小组之

间的交流,获得解决问题的途径和方法,使学生

在认知冲突中,处于一种主动,活跃的积极思维状

态,进而唤起学生的问题意识,产生学习需要。

4在观察比较中培养学生的创新意识

在课堂上,观察比较又是培养学生创新意识

的另一途径。学生的心理特征和年龄特点决定了

他们对生动形象的事物容易产生兴趣,容易理解

和记忆。根据这一特点,教学时,必须正确,合理的

利用声像,插图,让学生多角度观察对比,多途径

思考,多渠道解决实际问题,归纳出本质的东西,

培养学生的创新意识。

5在开放的练习中培养学生的创新意识

开放练习是培养学生个性创新的重要途径

之一。创新不是凭空臆造,需要有扎实的基础知

识和基本能力,但有了基础知识和基本能力,也不

一定能创造。学生在语文教学中获取了知识,养

成了能力,还懂得学以致用,这才是语文教学的最

终目的。因此,教师在教学中还要适当设计开放

性问题,给学生提供一个能够充分表现个性,激励

创新的空间。如在教学《水调歌头?明月几时有》

一文时,要求学生说出月亮的几个别称,背诵跟月

亮有关的诗句,学生们兴致盎然,说出了“玉兔,蟾

宫,婵娟”等几个别称,背诵了“月落乌啼霜满天”,

“秦时明月汉时关”,“明月松间照,清泉石上流”等

十余句跟月亮有关的诗句,从而在理解课文的基

础上学到了许多课本上学不到的鲜活的知识。

总之,在语文课堂教学中,培养学生的创新

意识,是一个新旧教学观念,教学结构,教学方法

更新的过程。要实现这一过程,教师必须加强学

习,提高自身素质和理论水平,转换角色,大胆改

革,勇于实践,从培养学生参与教学入手,在优化

课堂教学的过程中,鼓励学生不囿于教师和教材

的定论,敢于怀疑,大胆质疑,敢于超越权威学说,

从而促进学生创造思维的发展,培养学生的创造

精神,使创新真正成为学生的一种自觉的行为。

摘要:在新一轮课程改革中,作为语文教师,要大力推行素质教育,树立人本主义的教育思想,把自身“传道,授业,解惑”的角色转变为学生自主学习,探究性学习,合作学习的促进者,引导者和合作者。努力改革课堂结构,改进教学方法,通过创设问题情景,观察比较和在开放的练习中培养学生的创新意识,终身学习的能力。

关键词:语文教学;创新意识;培养

(上接46页)

北大青鸟推荐:Java精选笔试题(含答案解析)

北大青鸟推荐:Java精选笔试题(含答案解析)如果你是计算机专业出生,但是还没有找到工作的话,你就得补补技术了,一些关于面试、笔试的题要多刷一刷。有可能你知道答案,但是由于语言组织能力有所欠缺,所以面试官的印象不是很好,下面分享一些Java精选的鄙视题,希望对面试这者有帮助。 1,volatile关键字是否能保证线程安全?() 答案:否 volatile关键字用在多线程同步中,可保证读取的可见性,JVM只是保证从主内存加载到线程工作内存的值是最新的读取值,而非cache中。但多个线程对volatile的写操作,无法保证线程安全。 假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值,在线程1对count进行修改之后,会write到主内存中,主内存中的count变量就会变为6;线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6;导致两个线程及时volatile关键字修改之后,还是会存在并发的情况。 2,下面哪个流类属于面向字符的输入流( ) A、BufferedWriter B、FileInputStream C、ObjectInputStream D、InputStreamReader 答案:D Java的IO操作中有面向字节(Byte)和面向字符(Character)两种方式。

面向字节的操作为以8位为单位对二进制的数据进行操作,对数据不进行转换,这些类都是InputStream和OutputStream的子类。 面向字符的操作为以字符为单位对数据进行操作,在读的时候将二进制数据转为字符,在写的时候将字符转为二进制数据,这些类都是Reader和Writer的子类。 3,Java能不能不通过构造函数创建对象() A、能 B、不能 答案:A Java创建对象的几种方式: (1) 用new语句创建对象,这是最常见的创建对象的方法。 (2) 运用反射手段,调用https://www.wendangku.net/doc/0b17104740.html,ng.Class或者https://www.wendangku.net/doc/0b17104740.html,ng.reflect.Constructor类的newInstance()实例方法。 (3) 调用对象的clone()方法。 (4) 运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法。 (1)和(2)都会明确的显式的调用构造函数;(3)是在内存上对已有对象的影印,所以不会调用构造函数;(4)是从文件中还原类的对象,也不会调用构造函数。 4,下列哪个叙述是正确的() A.子类继承父类的构造方法。 B.abstract类的子类必须是非abstract类。 C.子类继承的方法只能操作子类继承和隐藏的成员变量。 D.子类重写或新增的方法也能直接操作被子类隐藏的成员变量。 答案:C 子类是不继承父类的构造方法的,而是必须调用其父类的构造方法。

Java API 试题

永隆 JAVA笔试题 一、选择题 1、关于Java 类的加载过程,下面哪些描述是正确的() A、在 Java 中,有四种类型的类加载器:BootStrapClassLoader、ExtClassLoader、AppClassLoader 以及用户自定义的ClassLoader。//Extension ClassLoader, System ClassLoader+用户自定义的classloader B、使用 new 关键字创建类实例时,其实就显示地包含了类的加载过程 C、在 Java 中,类的实例化流程分为两个部分:类的加载和类的实例化。类的加载又分为显式加载和隐式加载。 D、Class.forName 来加载类时,是通过 ExtClassLoader进行加载的。 //system classLoader 加载 2、关于HashMap的实现机制,下面哪些描述是正确的() A、HashMap中key-value 当成一个整体进行处理,系统总是根据数组的坐标来获得key-value 的存储位置。//没有存储顺序,无下标之说! B、HashMap基于哈希表的 Map 接口的实现,允许使用 null 值和 null 键。 C、如果HashMap中,如果Key的hash相同的话,HashMap将会出错。//会替换相应的value D、HashMap每次容量的扩增都是以2的倍数来增加。//大约获得2倍的桶数! 3、下面的代码执行输出正确的是() 1. public class test( 2. public int aMethod()[ 3. static int i=0; 4. i++; 5. return I; 6. ) 7. public static void main (String args[]){ 8. test test = new test(); 9. test.aMethod(); 10.int j = test.aMethod(); 11.System.out.printIn(j); 12.] 13.} A. 编译错误 B. 编译成功,打印出是“0” C. 编译成功,打印出是“1” D. 编译成功,打印出是“2” A 4、如何获取下面表单 select

类的加载

类从加载到虚拟机到卸载,它的整个生命周期包括:加载(Loading),验证(Validation),准备(Preparation),解析(Resolution),初始化(Initialization),使用(Using)和卸载(Unloading)。其中,验证、准备和解析部分被称为连接(Linking)。 加载: 在加载阶段,虚拟机主要完成三件事: 1.通过一个类的全限定名来获取定义此类的二进制字节流。 2.将这个字节流所代表的静态存储结构转化为方法区域的运行时数据结构。 3.在Java堆中生成一个代表这个类的https://www.wendangku.net/doc/0b17104740.html,ng.Class对象,作为方法区域数据的访问入口。 验证: 验证阶段作用是保证Class文件的字节流包含的信息符合JVM规范,不会给JVM造成危害。如果验证失败,就会抛出一个https://www.wendangku.net/doc/0b17104740.html,ng.VerifyError异常或其子类异常。验证过程分为四个阶段: 1.文件格式验证:验证字节流文件是否符合Class文件格式的规范,并且能被当前虚拟机正确的处理。 2.元数据验证:是对字节码描述的信息进行语义分析,以保证其描述的信息符合Java语言的规范。 3.字节码验证:主要是进行数据流和控制流的分析,保证被校验类的方法在运行时不会危害虚拟机。

4.符号引用验证:符号引用验证发生在虚拟机将符号引用转化为直接引用的时候,这个转化动作将在解析阶段中发生。 准备: 准备阶段为变量分配内存并设置类变量的初始化。在这个阶段分配的仅为类的变量(static修饰的变量),而不包括类的实例变量。对已非final的变量,JVM会将其设置成“零值”,而不是其赋值语句的值: pirvate static int size = 12; 那么在这个阶段,size的值为0,而不是12。final修饰的类变量将会赋值成真实的值。 解析: 解析过程是将常量池内的符号引用替换成直接引用。主要包括四种类型引用的解析。类或接口的解析、字段解析、方法解析、接口方法解析。 初始化: 在准备阶段,类变量已经经过一次初始化了,在这个阶段,则是根据程序员通过程序制定的计划去初始化类的变量和其他资源。这些资源有static{}块,构造函数,父类的初始化等。 至于使用和卸载阶段阶段,这里不再过多说明,使用过程就是根据程序定义的行为执行,卸载由GC完成。

【IT专家】来自加载类的Java Call类函数

本文由我司收集整编,推荐下载,如有疑问,请与我司联系 来自加载类的Java Call类函数 2011/02/25 1277 How would I, if possible, call a function in my Main class in the class that I load? (I know that is impossible to understand, so I’ll explain) ?如果可能的话,我如何在我加载的类中调用Main类中的函数? (我知道这是不可能理解的,因此我会解释) I.E: public class SomeClass public SomeClass //load a class here public void FuncToCall() {}//In a separate file, dynamically loaded.public class LoadedClass public LoadedClass //Call a function in the class that loads this SomeClass.FuncToCall(); So I would end up having 2 files: SomeClass.class and LoadedClass.class. I guess my main question is, how do I reference SomeClass in LoadedClass? ?因此我最终会得到2个文件:SomeClass.class和LoadedClass.class。我想我的主要问题是,如何在LoadedClass中引用SomeClass? **EDIT: So maybe I should better explain the use case. A java program dynamically loads the “SomeClass” script from a folder. The script then downloads a .jar file from the internet and opens and runs the “LoadedClass” script within that. How do I use functions in SomeClass in LoadedClass if SomeClass isn’t in the same .jar or in a .jar at all? ?因此也许我应该更好地解释用例。java程序从文件夹动态加载“SomeClass”脚本。然后,该脚本从Internet下载.jar文件,并在其中打开并运行“LoadedClass”脚本。如果SomeClass不在同一个.jar或.jar中,我如何在LoadedClass中的SomeClass中使用函数? ?你这样做.. ?If they are in different packages you have to either import the class or use the fully qualified name. ?如果它们位于不同的包中,则必须导入该类或使用完全限定的名称。

java如何写存储过程

Java中对存储过程的调用 一:Java如何实现对存储过程的调用: A:不带输出参数的 ---------------不带输出参数的---------------------------------- create procedure getsum @n int =0<--此处为参数--> as declare @sum int<--定义变量--> declare @i int set @sum=0 set @i=0 while @i<=@n begin set @sum=@sum+@i set @i=@i+1 end print 'the sum is '+ltrim(rtrim(str(@sum))) --------------在SQL中执行:-------------------- exec getsum 100 ------------在JAVA中调用:--------------------- JAVA可以调用但是在JAVA程序却不能去显示该存储过程的结果因为上面的存储 过程的参数类型int 传递方式是in(按值)方式 import java.sql.*; public class ProcedureTest { public static void main(String args[]) throws Exception { //加载驱动 DriverManager.registerDriver(new sun.jdbc.odbc.JdbcOdbcDriver()); //获得连接 Connection conn=DriverManager.getConnection("jdbc:odbc:mydata","sa",""); //创建存储过程的对象 CallableStatement c=conn.prepareCall("{call getsum(?)}"); //给存储过程的参数设置值 c.setInt(1,100); //将第一个参数的值设置成100 //执行存储过程 c.execute(); conn.close();

Java程序是如何运行的

Java程序是如何运行的 JVM是Java的运行时虚拟机,所有的Java程序都是在JVM沙箱中运行,每个Java程序就是一个独立的JVM进程。 谈到Java程序是如何运行的,首先需要理解的肯定是JVM是如何运行的,什么是JVM;要理解我们编写的Java程序,运行起来以后到底是什么样子,本质上就是弄清楚JVM是什么样子。 Java程序的代码是什么样的 Java诞生之初最大的卖点就是编写的代码跨平台可移植性,实现这种可移植性,是因为Java通过平台特定的虚拟机,运行中间的字节码,而不是直接编译成本地二进制代码实现,中间字节码也就是java文件编译后生成的.class文件,Jar包的话,实际上只是一系列.class文件的集合。 编写Java程序,首先需要一个入口点,在运行的时候通过指定MainClass来指定入口点,代码层面主类必须实现一个静态的main函数,运行时虚拟机会从MainClass.main开始执行指令,其他的逻辑只是import和函数调用了。 SDK自带的javac命令,负责将我们编程的Java代码,也就是.java文件,编译成平台无关的字节码;字节码可以在任何操作系统平台上,通过平台对应的JVM执行;JVM执行的时候,运行字节码,根据自己的平台特性,将字节码转换成平台相关的二进制码运行。 javac编译器运行的过程大致分为:词法分析(Token流)、语法分析(语法树)、语义分析(注解语法树),还有代码生成器,根据注解语法树,生成字节码, 语义分析阶段,编译器会做一些操作,将人类友好的代码,做一些处理,转换成更符合机器执行机制的代码,例如全局变量,魔法变量,依赖注入,注解这些魔法机制。大致分为以下步骤: 1. 给类添加默认构造函数 2. 处理注解 3. 检查语义的合法性并进行逻辑判断 4. 数据流分析 5. 对语法树进行语义分析(变量自动转换并去掉语法糖) JVM是什么 JVM = 类加载器 classloader + 执行引擎 execution engine + 运行时数据区域 runtime data area JVM就是运行编译好字节码的虚拟机,不同的操作系统和平台上,虚拟机将平台无关的字节码,编译成特定平台的指令去执行。我觉得,JVM首先是一个独立运行在操作系统上的进程。执行java命

JAVA反射机制(内含大量实例)

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。其中LEAD/LEAD++ 、OpenC++ 、MetaXa和OpenJava等就是基于反射机制的语言。最近,反射机制也被应用到了视窗系统、操作系统和文件系统中。 反射本身并不是一个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。可以看出,同一般的反射概念相比,计算机科学领域的反射不单单指反射本身,还包括对反射结果所采取的措施。所有采用反射机制的系统(即反射系统)都希望使系统的实现更开放。可以说,实现了反射机制的系统都具有开放性,但具有开放性的系统并不一定采用了反射机制,开放性是反射系统的必要条件。一般来说,反射系统除了满足开放性条件外还必须满足原因连接(Causally-connected)。所谓原因连接是指对反射系统自描述的改变能够立即反映到系统底层的实

际状态和行为上的情况,反之亦然。开放性和原因连接是反射系统的两大基本要素。 Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。 二、Java中的类反射: Reflection 是 Java 程序开发语言的特征之一,它允许运行中的Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。 1.检测类: 1.1 reflection的工作机制 考虑下面这个简单的例子,让我们看看 reflection 是如何工作的。

Java的数据结构相关的类实现原理

Java的数据结构相关的类实现原理 List接口 List是有序的Collection,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List中的位置,类似于数组下标)来访问List中的元素,这类似于Java的数组。 和下面要提到的Set不同,List允许有相同的元素。 除了具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。 实现List接口的常用类有LinkedList,ArrayList,Vector和Stack。 LinkedList List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。 此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。 所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。 注意,此实现不是同步的。如果多个线程同时访问一个链接列表,而其中至少一个线程从结构上修改了该列表,则它必须保持外部同步。(结构修改指添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使 用 Collections.synchronizedList 方法来“包装”该列表。最好在创建时完成这一操作,以防止对列表进行意外的不同步访问,如下所示: List list = Collections.synchronizedList(new LinkedList(...)); 此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在迭代器创建之后,如果从结构上对列表进行修改,除非通过迭代器自身的remove 或 add 方法,其他任何时间任何方式的修改,迭代器都将抛 出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒将来不确定的时间任意发生不确定行为的风险。 注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何硬性保证。快速失败迭代器尽最大努力抛出ConcurrentModificationException。因此,编写依赖于此异常的程序的方式是错误的,正确做法是:迭代器的快速失败行为应该仅用于检测程序错误。 ArrayList

java实验指导书

实验一java开发环境及语言基础 实验目的 (1)确保正确配置java开发环境。 (2)了解javac和java命令的使用。 (3)熟悉java中的运算符。 (4)掌握条件语句和循环语句的使用。 (5)掌握通过命令行参数接受数据。 (6)掌握用Scanner类接受数据。 实验内容 (1)在控制台中输入java命令,查看输入结果。 (2)编写一个java程序,计算半径为3.0的圆周长和面积并输出结果。 (3)求a+aa+aaa+...+a...a(n个)的和,其中a为1~9之间的整数。例如,当a=3、n=4时,求3+33+333+3333的和。 (4)给定一个正整数m,统计其位数,分别打印每一位数字,再按照逆序打印出各位数字。(5)用Scanner类方法输入三角形三边求三角形面积。 实验要求 (1)JDK的安装及配置。 (2)在DOS及eclipse下编辑、编译运行第一个java程序:hello world。 (3)求圆周长和面积用方法实现,主函数调用。 (4)从命令行输入1~9之间的整数a,当所求的和大与106时,输出相应的a值及所求的和值。 (5)用Scanner类的方法输入正整数m,m的值不应该超过99999,否则给出错误信息。应引入包:import java.util.Scanner,然后在需要的方法中实例化对象:Scanner sc = new Scanner(System.in),最后调用对象的next方法,如int n=nextInt(),接受整数。 实验二数组 实验目的 (1)掌握数组的定义和使用方法。 (2)熟悉数组的排序、查找的方法。 (3)巩固循环的使用。 实验内容 (1)使用for循环,将二维数组的行与列互换,即完成矩阵的转置。 (2)编写数组的排序程序。 (3)编写杨辉三角。 实验要求 (1)编写一个界面1 选择排序2 冒泡排序3插入排序4 快速排序5 退出 当选择1、2、3、4、5的时候完成相应的功能。 (2)杨辉三角形状为等腰三角形 实验三字符串 实验目的 (1)掌握正则表达式的使用。 (2)熟悉java的字符串。

java反射机制

Java的反射机制是Java特性之一,反射机制是构建框架技术的基础所在。灵活掌握Java反射机制,对大家以后学习框架技术有很大的帮助。 那么什么是Java的反射呢? 大家都知道,要让Java程序能够运行,那么就得让Java类要被Java虚拟机加载。Java类如果不被Java虚拟机加载,是不能正常运行的。现在我们运行的所有的程序都是在编译期的时候就已经知道了你所需要的那个类的已经被加载了。 Java的反射机制是在编译并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用在编译期并不知道的类。这样的特点就是反射。 那么Java反射有什么作用呢? 假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。 Java的反射机制它知道类的基本结构,这种对Java类结构探知的能力,我们称为Java类的“自审”。大家都用过Jcreator和eclipse。当我们构建出一个对象的时候,去调用该对象的方法和属性的时候。一按点,编译工具就会自动的把该对象能够使用的所有的方法和属性全部都列出来,供用户进行选择。这就是利用了Java反射的原理,是对我们创建对象的探知、自审。 Class类 要正确使用Java反射机制就得使用https://www.wendangku.net/doc/0b17104740.html,ng.Class这个类。它是Java反射机制的起源。当一个类被加载以后,Java虚拟机就会自动产生一个Class对象。通过这个Class对象我们就能获得加载到虚拟机当中这个Class对象对应的方法、成员以及构造方法的声明和定义等信息。 反射API ◆反射API用于反应在当前Java虚拟机中的类、接口或者对象信息 ◆功能 —获取一个对象的类信息. —获取一个类的访问修饰符、成员、方法、构造方法以及超类的信息. —检获属于一个接口的常量和方法声明. —创建一个直到程序运行期间才知道名字的类的实例. —获取并设置一个对象的成员,甚至这个成员的名字是 在程序运行期间才知道. —检测一个在运行期间才知道名字的对象的方法 利用Java反射机制我们可以很灵活的对已经加载到Java虚拟机当中的类信

Java开源架构技术学习重点(部分答案版)(1)

第一章 Strut2框架技术的入门 1、Struts2的是怎么产生的? Struts2是Struts的下一代产品,是在Struts1和WebWork的技术基础上进行了合并,全新的Struts2框架。其全新的Struts2的体系结构与Struts1的体系结构的差别巨大。Struts 2以WebWork为核心,采用拦截器的机制来处理用户的请求,这样的设计也使得业务逻辑控制器能够与Servlet API完全脱离开,所以Struts 2可以理解为WebWork的更新产品。因此Struts2和Struts 1有着太大的变化,但是相对于WebWork,Struts2只有很小的变化。 2、Struts2的设计模式是什么?采用这种设计模式有什么好处? MVC模式 MVC模式对于Web应用的开发无疑是一种非常先进的设计思想,无论选择 哪种语言,无论应用多复杂,它都能为理解分析应用模型提供最基本的分析方法, 为构造产品提供清晰的设计框架,为软件工程提供规范的依据。 1. 模型(Model) Model 部分包括业务逻辑层和数据库访问层。在Java Web 应用程序中,业务逻辑层一般由JavaBean或EJB构建。Model 部分就是业务流程或状态的处理以及业务规则的制定。业务流程的处理过程对其他层来说是黑箱操作,模型接受视图请求的数据,并返回最终的处理结果。业务模型的设计可以说是MVC最主要的组件。MVC并没有提供模型的设计方法,而只提供给用户应该组织管理这些模型,以便于模型的重构和提高重用性。 2. 视图(View) 在Java Web 应用程序中,View 部分一般用JSP 和HTML 构建,也可以是XHTML、XML、Applet和JavaScript。客户在View 部分提交请求,在业务逻辑层处理后,

java类加载机制

Java类加载机制(一) 译:ayi 第一次翻译,翻译得不是很好,请多多指点 我的邮箱:nonopo12345@https://www.wendangku.net/doc/0b17104740.html, 原文:https://www.wendangku.net/doc/0b17104740.html,/pub/a/onjava/2005/01/26/classloading.html 类加载是java特性的一个重量级的组成部分。尽管,java中“advanced topics”的发展,使java的类加载机制的地位有所下降。但每位编程着都应该知道这部分的工作机制,以及怎样去更好与其配合。这可以使我们节省很多时间,二不必要浪费在调试ClassNotFoundException, ClassCastException, 等。 这篇文章将从最基本的开始,比如代码和数据的关系和区别,以及他们怎么样关系起来形成一个实例或者对象。然后将会说到,java中怎样通过类加载器把代码加载到JVM中,以及java中实现的主要的几种类型的类加载器。然后在这篇文章中我们将会了解到java类加载机制的内幕,我们将使用最基本的代码来描述,这些代码执行与类加载器之后,但在加载一个类之前。在接下来的部分将使用一些例子来强调,对于开发者继承和开发自己的类加载器的必要性。接着将告诉你们怎样编写自己的类加载器,以及怎样使用它们去创建一个一般的能加载包括远程客户端辅助代码的类加载器引擎,以及怎样把它在JVM中定义,实例化,然后执行。习惯上,把J2EE-specific components 中说明的作为java类加载的规范,这篇文章正是从这本手册总结来的。 类和数据 一个类代表一段要执行的代码,然而数据则代表与这些代码相关联的某种状态。状态可以改变,代码不能改变。我们把一种特定状态与一个类关联起来时,就得到了这个类的一个实例。所以同一个类的不同实例有不同的状态,但都参照相同的代码。在java中,一个类通常它的代码就包含在一个 .class 文件中,虽然其中也包括异常。然而,在java运行时,每个类都会构造一个超类对象(first-class object),它们其实是https://www.wendangku.net/doc/0b17104740.html,ng.Class的实例。不论何时编译一个java文件,编译器都会在编译后的字节码中嵌入一个public, static, final型的字段class,这个字段表示的就是一个https://www.wendangku.net/doc/0b17104740.html,ng.Class型的实例。因为它是public类型的,我们可以通过标识符来访问它,像这样: https://www.wendangku.net/doc/0b17104740.html,ng.Class klass = Myclass.class; 只要一个类被加载到JVM,相同的类(强调:相同的类)将不会被重复加载。这将产生一个问题,什么才是相同的类?一个对象有一种特定状态和标识,对象总是与它所属类联系在一起,与这种状况相似,一个被加载到JVM中类也有特定的标识,接下来我们就阐述: 在java中,一个类通过认证的类全名来唯一标识。认证的类全名是由包名和类名两部分组

JAVA笔试题1

知识点: (1) 1.面向对象的软件开发有哪些优点? (1) 2.什么叫对象?什么叫类?类和对象有什么关系。 (1) 3.什么是包?把一个类放在包里有什么作用? (2) 4.作用域public、private、protected以及不写时(default)有什么区别? (2) 5.什么是方法?方法的结构是怎样的?设计方法应考虑哪些因素? (2) 6.什么是方法的覆盖?与方法的重载有何不同?方法的覆盖与属性的隐藏有何不同? (3) 7.什么是成员变量、局部变量、类变量和实例变量? (3) 8.什么是继承?什么是父类?什么是子类?继承的特性可给面向对象编程带来什么好处? (3) 9.什么是多态?面向对象程序设计为什么要引入多态的特性? (4) 10.“子类的域和方法的数目一定大于等于父类的域和方法的数目”,这种说法是否正确?为什么? (4) 11.父类对象与子类对象相互转化的条件是什么?如何实现它们的相互转化? (4) 12.接口与抽象类有哪些异同点? (4) 13.区分接口与抽象类分别在什么场合使用? (5) 14.一个类如何实现接口?实现某接口的类是否一定要重载该接口中的所有抽象方法? (5) 15.进程与线程的区别与联系? (5) 编程: (6) 1.统计一个字符串中出现某个字母的次数(注意区分大小写)。 (6) 2.编写一个程序,在主类中创建和调用方法sumf(),方法sumf()的功能是进行两个浮点数的加法运算。6知识点: 1.面向对象的软件开发有哪些优点? 面向对象设计是一种把面向对象的思想应用于软件开发过程中,指导开发活动的系统方法,是建立在“对象”概念基础上的方法学。所谓面向对象就是基于对象概念,以对象为中心,以类和继承为构造机制,来认识、理解、刻画客观世界和设计、构建相应的软件系统。 从面向过程到面向对象是程序设计技术的一个飞跃。人们之所以要采用面向对象的程序设计技术,其目的在于:按照与人类习惯思维方法一致的原则开发系统;提高代码的可重用性(或者称为复用性);提升程序的开发与运行效率;提高程序的可靠性与可维护性;提高程序的可扩展性;增强程序的可控制性。总之,面向对象的程序设计,能够有效分解、降低问题的难度与复杂性,提高整个求解过程的可控制性、可监视性和可维护性,从而获得较高的开发效率与可靠效果。 2.什么叫对象?什么叫类?类和对象有什么关系。 对象(Object)是一个应用系统中用来描述客观事物的实体,是具有特定属性(数据)和行为(方法)的基本运行单位,是类的一个特定状态下的实例。对象是一件事、一个实体、一个名词、一个可以想象为有自己的标识的任何东西。对象是类的实例化。概括来说:万物皆对象。对象具有状态,一个对象用数据值来描述它的状态。 类(Class)是Java代码的基本组织模块,是用以描述一组具有共同属性和行为的对象的基本原型,是对这组对象的概括、归纳与抽象表达。类是对象的模板,它定义了本类对象所应拥有的状态属性集及操作这组属性的行为方法集。是对一组有相同数据和相同操作的对象的定义,一个类所包含的方法和数据描述一组对象的共同属性和行为。

JAVA的反射机制与动态代理

JA V A的反射机制与动态代理 李海峰(QQ:61673110)-Andrew830314@https://www.wendangku.net/doc/0b17104740.html, 运行时类型信息(RunTime Type Information,RTTI)使得你在程序运行时发现和使用类型信息。RTTI主要用来运行时获取向上转型之后的对象到底是什么具体的类型。 1.Class对象: JAVA使用Class对象来执行RTTI。每个类都有一个Class对象,它用来创建这个类的所有对象,反过来说,每个类的所有对象都会关联同一个Class对象(对于数组来说,维数、类型一致的数组的Class对象才是相同的),每个对象的创建都依赖于Class对象的是否创建,Class对象的创建发生在类加载(https://www.wendangku.net/doc/0b17104740.html,ng.ClassLoader)的时候。 https://www.wendangku.net/doc/0b17104740.html,ng.Class类实现了Serializable、GenericDeclaration、Type、AnnotatedElement四个接口,分别实现了可序列化、泛型定义、类型、元数据(注解)的功能。 你可以把Class对象理解为一个类在内存中的接口代理(它代理了这个类的类型信息、方法签名、属性),JVM加载一个类的时候首先创建Class对象,然后创建这个类的每个实例的时候都使用这个Class对象。 Class只有一个私有的无参构造方法,也就是说Class的对象创建只有JVM可以完成。 如何验证同一个类的多个对象的Class对象是一个呢? Cf1 cf1 = new Cf1(); Class clazz = Cf1.class; System.out.println(cf1.getClass() == clazz); 我们知道==用来比较引用是否相等(也就是同一个引用),上面的输出语句结果是true。那么Class对象是否相等是JAVA对象中唯一可以使用==判断的。 如何获取Class对象: 1.所有的引用数据类型(类-类型)的类名、基本数据类型都可以通过.class方式获取其Class 对象(对于基本数据类型的封装类还可以通过.TYPE的方式获取其Class对象,但要注意.TYPE实际上获取的封装类对应的基本类型的Class对象的引用,那么你可以判断出int.class==Integer.TYPE返回true,int.class==Integer.class返回false!),通过这种方式不会初始化静态域,使用.class、.TYPE的方式获取Class对象叫做类的字面常量; 2.Class的forName(String name)传入一个类的完整类路径也可以获得Class对象,但由于使用的是字符串,必须强制转换才可以获取泛型的Class的Class对象,并且你必须获取这个方法可能抛出的ClassNotFoundException异常。 2.对于引用数据类的引用(必须初始化),可以通过Object类继承的getClass()方法获取这个引用的Class对象,由于引用已经被初始化,所以这种方式也不会初始化静态域,因为静态域已经被初始化过。另外,前面两种方式如果说是创建Class对象,那么这种方式应该是取得Class对象,因为类的实例已经被创建,那么Class对象也一定早就被创建。 Class的常用方法: l forName(String name):这是一个静态方法,传入的参数是一个类的完整类路径的字符串,返回这个类的Class对象,前面说过Class对象的创建发生在类的加载时,所以这个方法会导致静态成员被调用; l forName(String name,boolean initialize,ClassLoader loader):这是上面的方

JAVA类与对象的创建

试验四 类和对象的创建 一.类的定义 类是组成Java程序的基本要素。类封装了一类对象的状态和方法。类用来定义对象的模板。 类的实现包括两部分:类声明和类体。基本格式为: 修饰符class类名[extends父类名]{ /*类体的内容*/ } 1.类声明 以下是一个类声明的例子。 class People成为类声明,People是类名。习惯上,类名的第一个字母大写,但这不是必须的。类的名字不能是Java中的关键字,要符合标识符规定,即类的名字可以由字母、下划线、数字或美元符号组成,并且第一个字母不能是数字。但给类命名时,最好遵守下列规则: (1)如果类名使用拉丁字母,那么名字的首写字母使用大写字母,如Hello、Time、People等。 (2)类名最好容易识别,当类名由几个“单词”复合而成时,每个单词的首写字母使用大写,如BeijingTi me、AmericanGame、HelloChina等。 2.类体 编写类的目的是为了描述一类事物共有的属性和功能,描述过程由类体来实现。类声明之后的一对大括号“{”、“}”以及它们之间的内容称为类体,大括号之间的内容称为类体的内容。 类体的内容由两部分构成:一部分是变量的定义,用来刻画属性;另一部分是方法的定义,用来刻画功能。 下面是一个类名为“Trapezia”的类,类体内容的变量定义部分定义了4个float类型变量:top、bottom、h igh和laderArea,方法定义部分定义了两个方法:“getArea”和“setHigh”。

二.对象 1.对象的创建 创建一个对象包括对象的声明和为对象分配内存两个步骤。 (1)对象的声明。 一般格式为: 类的名字对象名字; 如: 这里People是类的名字,zhubajie是我们声明的对象的名字。 (2)为声明的对象分配内存。 使用new运算符和类的构造方法为声明的对象分配内存,如果类中没有构造方法,系统会调用默认的构造方法(你一定还记得构造方法的名字必须和类名相同这一规定),如: 例1: 「注」如果类里定义了一个或多个构造方法,那么Java不提供默认的构造方法。 2.对象的使用 对象不仅可以改变自己变量的状态,而且还拥有了使用创建它的那个类中的方法的能力,对象通过使用这些方法可以产生一定的行为。 通过使用运算符“.”,对象可以实现对自己的变量访问和方法的调用。 例2:

JAVA中的反射机制

JAVA中的反射机制 一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。 反射是java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高! 看概念很晕的,继续往下看。 二,反射机制的作用: 1,反编译:.class-->.java 2,通过反射机制访问java对象的属性,方法,构造方法等; 这样好像更容易理解一些,下边我们具体看怎么实现这些功能。 三,在这里先看一下sun为我们提供了那些反射机制中的类: https://www.wendangku.net/doc/0b17104740.html,ng.Class; https://www.wendangku.net/doc/0b17104740.html,ng.reflect.Constructor; https://www.wendangku.net/doc/0b17104740.html,ng.reflect.Field; https://www.wendangku.net/doc/0b17104740.html,ng.reflect.Method; https://www.wendangku.net/doc/0b17104740.html,ng.reflect.Modifier; 很多反射中的方法,属性等操作我们可以从这四个类中查询。还是哪句话要学着不断的查询API,那才是我们最好的老师。 四,具体功能实现:

1,反射机制获取类有三种方法,我们来获取Employee类型 [java]view plain copy print? 1.//第一种方式: 2.Class c1 = Class.forName("Employee"); 3.//第二种方式: 4.//java中每个类型都有class 属性. 5.Class c2 = Employee.class; 6. 7.//第三种方式: 8.//java语言中任何一个java对象都有getClass 方法 9.Employee e = new Employee(); 10.Class c3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee) 2,创建对象:获取类以后我们来创建它的对象,利用newInstance: 1.Class c =Class.forName("Employee"); 2. 3.//创建此Class 对象所表示的类的一个新实例 4.Objecto = c.newInstance(); //调用了Employee的无参数构造方法. 3,获取属性:分为所有的属性和指定的属性: a,先看获取所有的属性的写法: 1.//获取整个类 2. Class c = Class.forName("https://www.wendangku.net/doc/0b17104740.html,ng.Integer"); 3.//获取所有的属性? 4. Field[] fs = c.getDeclaredFields(); 5. 6.//定义可变长的字符串,用来存储属性 7. StringBuffer sb = new StringBuffer(); 8.//通过追加的方法,将每个属性拼接到此字符串中 9.//最外边的public定义 10. sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n"); 11.//里边的每一个属性 12.for(Field field:fs){ 13. sb.append("\t");//空格 14. sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如 public,static等等 15. sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字 16. sb.append(field.getName()+";\n");//属性的名字+回车

相关文档
相关文档 最新文档