1 Day01 02-eclipse使用和程序断点调试
1.1 Eclipse的使用
工作空间目录是纯英语无空间的路径
在eclipse下Java编写和操作程序,以及java运行环境的配置。
新建java工程day01可配置在弹出窗口jre
工程右键属性可配置编辑器的版本
1.2 调试程序
1.3 Debug窗口
Resume(F8)下一个断点
Step into(F5)进入函数等
Step over(F6)下一行代码
Step return(F7)返回调用的下一行
Drop to Frame回到当前方法的第一行,
Terminate (F12)终止虚拟机,程序结束。(调试后使用)
右键watch观察变量的值
1.4 Breakpoints窗口
因此断点被移除
1.5 注意断点
1. 调整后,删除断点
2. 调整后,断点必须结束JVM。
2 03-eclipse常用快捷键
MyEclipse默认编码设置工作空间utf-8.使新建工程使用默认编码
菜单栏——Window / Preferences / General / Workspace 。
内容提示:Alt / Content Assist
选择多行代码,按Tab按钮向右推整块,按钮Shift Tab是整块向左缩进
快速修复:Ctrl 1
导包:Ctrl shift O
格式化代码块:ctrl shift F
向前向后:Alt 方向键(left right arrow)查看源代码时
添加注释 Ctrl Shift /
除去注释 Ctrl Shift \
查看源代码 Ctrl 单击 ctrl shift t
检查方法说明:F2
重置透视图 Window menu下
更改为大写 Ctrl Shift X
更改为小写 Ctrl Shift Y
复制行 Ctrl Alt 向下键(有些不能用)
检查继承关系Ctrl T
查看快捷键Ctrl shift L
3 04-junit测试框架
在Outline右键在窗口方法上Run As /JUnit Test 测试某种方法,类上右键run as /JUnit Test 测试这一类的所有方法
1、用junit单元测试时,必须在每种测试方法中添加@Test注解
2、用@Before注释是在每种测试方法之前执行的。
3、用@After注释是在每种测试方法后执行的。
4、用@BeforeClass 注释的静态方法是在所有方法被测试之前执行的方法,就像类中的结构方法一样。初始化一些需要使用的变量和其他资源。
5、用@AterClass注释的静态方法是在所有测试方法之后执行的。c 中析构函数。用于释放一些资源。
6.使用断言Assert可以判断被测方法的返回值是否与您预期的相同。
//person.java
package cn.itcast.elclipse;
public class Person {
public void eat()
{
System.out.println("eating.");
}
public String run()
{
System.out.println("runing.");
return "1";
}
} //demo4.java
package cn.itcast.elclipse;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class Demo4 {
@Before
public void before(){
System.out.println("before");
}
@Test
public void testRun()
{
Person p=new Person();
p.run();
}
@Test
public void testEat(){
Person p=new Person();
p.eat();
}
@After
public void after(){
System.out.println("after");
}
}
//Demo5.java
package cn.itcast.elclipse;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class Demo5 {
@BeforeClass
public void beforeClass(){
System.out.println("beforeclass");
}
@Test
public void testRun()
{
Person p=new Person();
p.run();
}
@Test
public void testEat(){
Person p=new Person();
p.eat();
}
@AfterClass
public void afterClass(){
System.out.println("afterclass");
}
} //Demo6.java
package cn.itcast.elclipse;
import junit.framework.Assert;
import org.junit.Test;
public class Demo6 {
@Test
public void testRun()
{
Person p=new Person();
Assert.assertEquals("2", p.run());
}
}
4 java5.静态导入和自动装箱拆卸.avi
JDK五中新增了许多新的java使用这些新语法可以帮助开发人员编写更高效、清晰、安全的代码。
静态导入 自动装箱/拆箱 增强for循环 可变参数 枚举反射内省 泛型 元数据
4.1 静态导入
JDK 1.5 增加的静态导入语法用于导入类的静态属性或方法。使用静态导入可以简化程序对类静态属性和方法的调用。
语法:
Import static 包名.类名.静态属性|静态方法|*
例如:
4.2 自动装箱/拆箱
JDK5.0语法允许开发人员直接将基本数据类型赋予相应的包装类变量, 或者赋给 Object 类型变量称为自动装箱。
自动拆箱与自动装箱相反,即将包装对象直接赋予相应的基本类型变量。
典型应用:
静态导入 自动装箱/拆箱
import static java.lang.System.out
import static java.lang.Math.*
//Demo1
package cn.itcast.demo;
import static java.lang.System.out;
import static java.util.Arrays.*;
public class Demo1 {
public static void main(String[] args) {
out.print("main");
int []a=new int[6,5,3};
sort(a);
for(int i:a)
out.print(i);
}
}
// main356 package cn.itcast.demo;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Demo2 {
public static void main(String[] args) {
Integer i=1;//装箱
int j=i;//拆箱
//典型应用
List list = new ArrayList();
list.add(1);
int k = (Integer)list.get(0);
Iterator it=list.iterator();
while(it.hasNext())
{
int m=(Integer)it.next();//拆箱
}
}
}
5 06-增强for循环
5.1 增强for循环
引入增强for循环原因:在JDK5以前的本中,遍历数组或集合中的元素,需先获得数组的长度或集合的迭代器,比较麻烦!
因此JDK5中定义了一种新的语法——增强for循环,以简化此类操作。增强for循环只能用在数组、或实现Iterator接口的集合类上
语法格式:
for(变量类型变量 :需迭代的数组或集合){
}
Map map=new HashMap();
//Map map2=new LinkedHashMap<k v>();
map.put("1", "aaa");
map.put("2", "bbb");
map.put("3", "ccc");
//传统方式1
Set set=map.keySet();
Iterator it=set.iterator();
while(it.hasNext()){
String key=(String)it.next();
String value=(String) map.get(key); System.out.println("key="+key+",value="+value);
} //增强for循环的1种方式
for(Object obj:map.keySet()){
String key2=(String)obj;
String value2=(String)map.get(key2); System.out.println("key2="+key2+",value2="+value2);
}
//传统方式2
Set set2=map.entrySet();
Iterator it2=set2.iterator();
while(it2.hasNext()){
Map.Entry entry=(Entry)it2.next(); System.out.println("key="+entry.getKey()+",value="+entry.getValue());
} //增强for循环的2种方式
for(Object obj:map.entrySet()){
Map.Entry entry3=(Entry) obj;
String key3=(String) entry3.getKey();
String value3=(String) entry3.getValue();
System.out.println("key3="+key3+",value3="+value3);
}
//增强for循环需要注意的问题:只适合取数据
int arr[]={1,2,3};
for(int i: arr){
i=10;
}
System.out.println(arr[0]); // 1
List li=new ArrayList();
li.add("1");
for(Object obj : li){
obj="888";
}
System.out.println(li.get(0));// 1
6 可变参数
测试JDK中具有可变参数的类Arrays.asList()方法。分别传多个参、传数组,传数组又传参的情况。
注意:传入基本数据类型数组的问题。
从JDK 5开始, Java 允许为方法定义长度可变的参数。语法:
public void foo(int … args){
}
注意事项:
调用可变参数的方法时, 编译器将自动创建一个数组保存传递给方法的可变参数,因此,程序员可以在方法体中以数组的形式访问可变参数
可变参数只能处于参数列表的最后, 所以一个方法最多只能有一个长度可变的参数
public void testSum(){
sum(1,2,3,4);
int arr[]={5,6,7};
sum(arr);
}
public void sum(int ...nums){
//可变参数当成数组
int sum=0;
for(int i:nums){
sum+=i;
}
System.out.println(sum);
} public void bb(){
//public static <t> List<t>asList(T... a)
List list=Arrays.asList("1","2","3");
System.out.println(list);//[1, 2, 3]
String arr[]={"1","2","3","4"};
list=Arrays.asList(arr);
System.out.println(list);//[1, 2, 3, 4]
int nums[]={1,2,3,4,5};
list=Arrays.asList(nums);
System.out.println(list);//[[I@120d62b]
Integer nums2[]={1,2,3,4,5};
list=Arrays.asList(nums2);
System.out.println(list);//[1, 2, 3, 4, 5]
}
//可变参数注意的问题
//public void aa(int ...nums,int s){}//不可以
//public void bb(int s ,int ...nums)//可以
7 枚举类
为什么需要枚举?
一些方法在运行时,它需要的数据不能是任意的,而必须是一定范围内的值,此类问题在JDK5以前采用自定义带有枚举功能的类解决,Java5以后可以直接使用枚举予以解决。
JDK 5新增的 enum 关键字用于定义一个枚举类。
7.1 枚举类
枚举类具有如下特性:
枚举类也是一种特殊形式的Java类。
枚举类中声明的每一个枚举值代表枚举类的一个实例对象。
与java中的普通类一样,在声明枚举类时,也可以声明属性、方法和构造函数,但枚举类的构造函数必须为私有的(这点不难理解)。
枚举类也可以实现接口、或继承抽象类。
JDK5中扩展了swith语句,它除了可以接收int, byte, char, short外,还可以接收一个枚举类型。
若枚举类只有一个枚举值,则可以当作单态设计模式使用。
练习:请编写一个关于星期几的枚举WeekDay,要求:
枚举值:Mon、Tue 、Wed 、Thu 、Fri 、Sat 、Sun
该枚举要有一个方法,调用该方法返回中文格式的星期。
Java中声明的枚举类,均是java.lang.Enum类的孩子,它继承了Enum类的所有方法。常用方法:
name()
ordinal()//返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
valueof(Class enumClass, String name) //返回带指定名称的指定枚举类型的枚举常量。
//String str=”B”;Grade g=Grade.valueOf(Grade.class,str);
values() 此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便。
package cn.itcast.enumeration;
import org.junit.Test;
public class Demo1 {
@Test
public void test() {
print(Grade.B);
}
public void print(Grade g) // A B C D E
{
String value=g.getValue();
System.out.println(value);
}
}
/*
* class Grade{ private Grade(){ }
* public static final Grade A=new Grade();
* public static final Grade B=new Grade();
* public static final Grade C=new Grade();
* public static final Grade D=new Grade();
* public static final Grade E=new Grade();
* }
*/
//如何定义枚举的构造函数、方法、字段
enum Grade {// class A 100-90 B 89-80 C 79-70 D 69-60 E 59-0
A("100-90"), B("89-80"), C("79-70"), D("69-60"), E("59-0");// object
private String value;
private Grade(String value){
this.value=value;
}
public String getValue(){
return this.value;
}
} package cn.itcast.enumeration2;
import org.junit.Test;
public class Demo1 {
@Test
public void test() {
print(Grade.B); //89-80,良
}
public void print(Grade g) // A B C D E
{
String value=g.getValue();
String value2=g.localeValue();
System.out.println(value+","+value2);
}
}
//带抽象方法的枚举
enum Grade {// class A 100-90优 B 89-80良 C 79-70 一般D 69-60差 E 59-0不及格
A("100-90"){
public String localeValue(){
return "优";
}
},
B("89-80"){
public String localeValue(){
return "良";
}
},
C("79-70"){
public String localeValue(){
return "一般";
}
},
D("69-60"){
public String localeValue(){
return "差";
}
},
E("59-0"){
public String localeValue(){
return "不及格";
}
};// object
private String value;
private Grade(String value){
this.value=value;
}
public String getValue(){
return this.value;
}
public abstract String localeValue();
}
7.2 反射什么—Class类
反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。
Class类用于表示.class文件,画图演示一个对象的创建过程。
如何得到某个class文件对应的class对象。
类名.class, 对象.getClass() Class.forName(“类名”)
以上三种方式,JVM都会把相应class文件装载到一个class对象中(只装载一次)
创建类的实例:Class.newInstance方法
数组类型的Class实例对象
Class.isArray()
总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int,void…
反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。
掌握反射技术的要点在于:如何从一个class中反射出各个组成部分。反射出来的对象怎么用。
7.3 Constructor类
Constructor类代表某个类中的一个构造方法
得到某个类所有的构造方法:
例子:Constructor [] constructors= Class.forName("java.lang.String").getConstructors();
得到某一个构造方法:
例子: //获得方法时要用到类型
Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式: String str = (String)constructor.newInstance(new StringBuffer("abc"));
Class.newInstance()方法:例子:String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
7.4 Field类
Field类代表某个类中的一个成员变量
问题:得到的Field对象是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,而该类的实例对象有多个,如果是与对象关联,哪关联的是哪个对象呢?所以字段fieldX 代表的是x的定义,而不是具体的x变量。(注意访问权限的问题)
示例代码:
ReflectPoint point = new ReflectPoint(1,7);
Field y = Class.forName("cn.itcast.corejava.ReflectPoint").getField("y");
System.out.println(y.get(point));
//Field x = Class.forName("cn.itcast.corejava.ReflectPoint").getField("x");
Field x = Class.forName("cn.itcast.corejava.ReflectPoint").getDeclaredField("x");
x.setAccessible(true);
System.out.println(x.get(point));
7.5 Method类
Method类代表某个类中的一个成员方法
得到类中的某一个方法:
例子: Method charAt = Class.forName("java.lang.String").getMethod("charAt", int.class);
调用方法:
通常方式:System.out.println(str.charAt(1));
反射方式:System.out.println(charAt.invoke(str, 1));
如果传递给Method对象的invoke()方法的第一个参数为null,这有着什么样的意义呢?说明该Method对象对应的是一个静态方法!
jdk1.4和jdk1.5的invoke方法的区别:
Jdk1.5:public Object invoke(Object obj,Object... args)
Jdk1.4:public Object invoke(Object obj,Object[] args),即按jdk1.4的语法,需要将一个数组作为参数传递给invoke方法时,数组中的每个元素分别对应被调用方法中的一个参数,所以,调用charAt方法的代码也可以用Jdk1.4改写为 charAt.invoke(“str”, new Object[]{1})形式。
7.6 用反射方式执行某个类中的main方法
目标:写一个程序,这个程序能够根据用户提供的类名,去执行该类中的main方法。用普通方式调完后,大家要明白为什么要用反射方式去调啊?
问题:
启动Java程序的main方法的参数是一个字符串数组,即public static void main(String[] args),通过反射方式来调用这个main方法时,如何为invoke方法传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题。
解决办法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"}); ,编译器会作特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了
package cn.itcast.reflect;
import java.io.InputStream;
import java.util.List;
public class Person {
public String name="aaaa";
private int password;
private static int age=23;
public Person(){
System.out.println("person");
}
public Person(String name){
this.name=name;
System.out.println("person name");
}
public Person(String name,int password){
this.name=name;
System.out.println("person name password");
}
private Person(List list){
System.out.println("list");
}
public void aa1(){
System.out.println("aa1");
}
public void aa1(String name,int password){
System.out.println("name= "+name+" password="+password);
}
public Class[] aa1(String name,int[] password){
return new Class[]{String.class};
}
private void aa1(InputStream in){
System.out.println(in);
}
public static void aa1(int num){
System.out.println(num);
}
public static void main(String []args){
System.out.println("main");
}
} package cn.itcast.reflect;
import java.lang.reflect.Field;
import org.junit.Test;
//反射类的字段
public class Demo4 {
//public String name="aaaa";
@Test
public void test1() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Field f=clazz.getField("name");
Person p=new Person();
Object value= f.get(p);//获取字段值
Class type=f.getType();//字段类型
System.out.println(type);//class java.lang.String
if(type.equals(String.class)){
String S_value=(String)value;
System.out.println(S_value);//aaaa
}
//设置值
f.set(p, "ppppp");
System.out.println(f.get(p));//ppppp
System.out.println(String.class);//class java.lang.String
}
//private int password;
@Test
public void test2() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Field f=clazz.getDeclaredField("password");
f.setAccessible(true);
Person p=new Person();
f.set(p, 123);
System.out.println(f.get(p));//123
}
//private static int age=23;
@Test
public void test3() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Field f=clazz.getDeclaredField("age");
f.setAccessible(true);
System.out.println(f.get(null));//23
}
}
package cn.itcast.reflect;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
//反射类的构造函数,创建类的对象
public class Demo2 {
//public Person()
@Test
public void test1() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Constructor c=clazz.getConstructor(null);
Person p=(Person) c.newInstance(null);//person
System.out.println(p.name);//aaaa
}
//public Person(String name)
@Test
public void test2() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Constructor c=clazz.getConstructor(String.class);
Person p=(Person) c.newInstance("abc");//person name
System.out.println(p.name);//abc
}
//public Person(String name,int password)
@Test
public void test3() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Constructor c=clazz.getConstructor(String.class,int.class);
Person p=(Person) c.newInstance("abc",999);//person name password
System.out.println(p.name);//abc
}
//private Person(List list)
@Test
public void test4() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Constructor c=clazz.getDeclaredConstructor(List.class);
c.setAccessible(true);//暴力反射,统统打开访问权限
Person p=(Person) c.newInstance(new ArrayList());//list
System.out.println(p.name);//aaaa
}
//创建对象的另外一种途径,无参构造方法,等效test1
public void test5() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Person p=(Person) clazz.newInstance();
System.out.println(p.name);//aaaa
}
} package cn.itcast.reflect;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import org.junit.Test;
//反射方法
public class Demo3 {
// public void aa1()
@Test
public void test1() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Method method=clazz.getMethod("aa1", null);
Person p=new Person();//person
method.invoke(p, null);//aa1
}
//public void aa1(String name,int password)
@Test
public void test2() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Method method=clazz.getMethod("aa1", String.class,int.class);
Person p=new Person();//person
method.invoke(p, "xxxx",99);//name= xxxx password=99
}
//public Class[] aa1(String name,int[] password)
@Test
public void test3() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Method method=clazz.getMethod("aa1", String.class,int[].class);
Person p=new Person();//person
Class cs[]=(Class[]) method.invoke(p, "xxxx",new int[]{1,2,3});//name= xxxx password=99
System.out.println(cs[0]);//class java.lang.String
}
//private void aa1(InputStream in)
public void test4() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Method method=clazz.getDeclaredMethod("aa1",InputStream.class);
method.setAccessible(true);
Person p=new Person();//person
method.invoke(p,new FileInputStream("C:\\1.txt"));//
}
//public static void aa1(int num)
public void test5() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Method method=clazz.getMethod("aa1",int.class);
method.invoke(null,777);//777 静态方法调用不需要对象,给对象也行
}
// public static void main(String []args){
public void test6() throws Exception{
Class clazz=Class.forName("cn.itcast.reflect.Person");
Method method=clazz.getMethod("main",String [].class);
//method.invoke(null,new String[]{"a","c"});//Wrong
//method.invoke(null,"a","c");//Wrong
String []str={"x","y","z"};
method.invoke(null, (Object)str);
method.invoke(null, new Object[]{new String[]{"a","c"} });
method.invoke(null, (Object)new String[]{"a","c"});
}
}
7.7 用反射技术实现一个简单的web服务器
内省(Introspector) — JavaBean
Introspector 类为通过工具学习有关受目标 Java Bean 支持的属性、事件和方法的知识提供了一个标准方法。
什么是JavaBean和属性的读写方法?
有get或set方法就是一个属性,另外所有类继承了Object类的getClass()方法,所以还有一个属性class。
访问JavaBean属性的两种方式:
直接调用bean的setXXX或getXXX方法。
通过内省技术访问(java.beans包提供了内省的API),内省技术访问也提供了两种方式。
通过PropertyDescriptor类操作Bean的属性
通过Introspector类获得Bean对象的 BeanInfo,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后通过反射机制来调用这些方法。
什么情况下用内省?
package cn.itcast.introspector;
//该类共有5个属性
public class Person {
private String name;
private String password;
private int age;
public void setAb(int a){
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setPassword(String password) {
this.password = password;
}
public void setAge(int age) {
this.age = age;
}
} package cn.itcast.introspector;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Test;
public class Demo1 {
//得到bean所有属性
public void test1() throws IntrospectionException{
BeanInfo info=Introspector.getBeanInfo(Person.class);
//去掉Object里的属性
BeanInfo info2=Introspector.getBeanInfo(Person.class,Object.class);
PropertyDescriptor[] pds=info.getPropertyDescriptors();
for(PropertyDescriptor pd:pds){
System.out.println(pd.getName());
//ab age class name password
}
}
//操纵bean的指定属性:age
@Test
public void test2() throws Exception{
Person p=new Person();
PropertyDescriptor pd=new PropertyDescriptor("age", Person.class);
//得到属性的写方法,为属性赋值
Method method=pd.getWriteMethod();
method.invoke(p, 45);
System.out.println(p.getAge());//45
//获取属性的值
method=pd.getReadMethod();
System.out.println(method.invoke(p, null));//45
}
//高级内容,获取当前操作的属性的类型
@Test
public void test3() throws Exception{
Person p=new Person();
PropertyDescriptor pd=new PropertyDescriptor("age", Person.class);
//得到属性的写方法,为属性赋值
Method method=pd.getWriteMethod();
System.out.println(pd.getPropertyType());//int
method.invoke(p, 45);
System.out.println(p.getAge());//45
//获取属性的值
method=pd.getReadMethod();
System.out.println(method.invoke(p, null));//45
}
}
7.8 内省—beanutils工具包
Apache组织开发了一套用于操作JavaBean的API,这套API考虑到了很多实际开发中的应用场景,因此在实际开发中很多程序员使用这套API操作JavaBean,以简化程序代码的编写。
在工程下新建lib目录,导入commons-beanutils-1.8.3.jar 和支持包commons-logging-1.1.1.jar
选中两个包,右键build path/add to build path
Beanutils工具包的常用类:
BeanUtils
PropertyUtils
ConvertUtils.regsiter(Converter convert, Class clazz)
自定义转换器
package cn.itcast.beanutils;
import java.util.Date;
public class Person {
private String name;
private String password;
private int age;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setPassword(String password) {
this.password = password;
}
public void setAge(int age) {
this.age = age;
}
} package cn.itcast.beanutils;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConversionException;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import org.junit.Test;
//使用beanUtils操纵bean的属性 ( 第三方)
public class Demo1 {
@Test
public void test1() throws Exception{
Person p=new Person();
BeanUtils.setProperty(p, "age", 456);
System.out.println(p.getAge());//456
}
@Test
public void test2() throws Exception{
String name="aaaa";
String age="123";
String password="pw";
Person p=new Person();
//支持8种基本类型自动转换
BeanUtils.setProperty(p, "name", name);
BeanUtils.setProperty(p, "age", age);
BeanUtils.setProperty(p, "password", password);
System.out.println(p.getName());//aaaa
System.out.println(p.getAge());//123
System.out.println(p.getPassword());//pw
}
@Test
public void test3() throws Exception{
String birthday="1983-12-1";
//为了让日期赋值到bean的birthday属性上,给beanUtils注册一个日期转换器
//ConvertUtils.register(converter, clazz);
ConvertUtils.register(new Converter(){
public Object convert(Class type, Object value) {
if(value==null) return null;
if(!(value instanceof String)){
throw new ConversionException("只支持String类型的转换");
}
String str=(String)value;
if(str.trim().equals("")) return null;
SimpleDateFormat df=new SimpleDateFormat("yyyy-MM-dd",Locale.US);
try {
return df.parse(str);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}, Date.class);
Person p=new Person();
BeanUtils.setProperty(p, "birthday", birthday);
System.out.println(p.getBirthday());//pw
System.out.println("___"+BeanUtils.getProperty(p, "birthday"));
}
public void test5() throws Exception {
Map map=new HashMap();
map.put("name", "aaa");
map.put("password", "123");
map.put("brithday", "1980-09-09");
ConvertUtils.register(new DateLocaleConverter(), Date.class);
Person p=new Person();
//用map集合填充bean属性,map关键字和bean属性要一致
BeanUtils.populate(p, map);
}
}
7.9 泛型(Generic)—泛形的作用
JDK5以前,对象保存到集合中就会失去其特性,取出时通常要程序员手工进行类型的强制
转换,这样不可避免就会引发程序的一些安全性问题。例如:
ArrayList list = new ArrayList();
list.add("abc");
Integer num = (Integer) list.get(0); //运行时会出错,但编码时发现不了
list.add(new Random());
list.add(new ArrayList());
for(int i=0;i<list.size jdk5>为例:念着typeof
ArrayList<e>中的E称为类型参数变量
ArrayList<integer>中的Integer称为实际类型参数
整个称为ArrayList<e>泛型类型
整个ArrayList<integer>称为参数化的类型ParameterizedType
7.10 泛型典型应用
使用迭代器迭代泛形集合中的元素。
使用增强for循环迭代泛形集合中的元素。
存取HashMap中的元素。
使用泛形时的几个常见问题:
使用泛形时,泛形类型须为引用类型,不能是基本数据类型
//使用泛型时,如果两边都使用到泛型,两边必须一样
ArrayList<string> list = new ArrayList<object>(); //bad
ArrayList<object> list = new ArrayList<string>(); //bad
ArrayList<string> list = new ArrayList ();//ok
ArrayList list = new ArrayList<string>();//ok
package cn.itcast.generic;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class Demo1 {
@Test
public void test1(){
List list=new ArrayList();
list.add("111");
list.add("222");
list.add("333");
//传统方式手工转换
String i=(String) list.get(0);
//下面注释代码手工转换编辑不报错,运行错误
//Integer ii=(Integer) list.get(0);
System.out.println(i);
}
@Test
public void test2(){
List <string>list=new ArrayList<string>();
list.add("111");
list.add("222");
list.add("333");
//现在不需要强制转换
String i=list.get(0);
//下面注释代码编译通不过
//Integer ii=(Integer) list.get(0);
System.out.println(i);
}
} package cn.itcast.generic;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
public class Demo2 {
@Test
public void test1(){
List <string>list=new ArrayList<string>();
list.add("111");
list.add("222");
list.add("333");
//传统
Iterator<string> it=list.iterator();
while(it.hasNext()){
String value=it.next();
System.out.println(value);
}
//增强for
for(String s:list)
System.out.println(s);
}
@Test
public void test2(){
Map<integer> map=new HashMap<integer>();
map.put(1, "aaa");
map.put(2, "bbb");
map.put(3, "ccc");
//传统 keyset entryset
Set <map.entry string>> set=map.entrySet();
Iterator <map.entry string>>it=set.iterator();
while(it.hasNext()){
Map.Entry<integer string>entry=it.next();
int key=entry.getKey();
String value=entry.getValue();
System.out.println(key+"="+value);
}
//增强for(重点)
for(Map.Entry<integer string> entry:map.entrySet()){
int key=entry.getKey();
String value=entry.getValue();
}
}
}
7.11 自定义泛形——泛型方法
Java程序中的普通方法、构造方法和静态方法中都可以使用泛型。方法使用泛形前,必须对泛形进行声明,语法:<t>,T可以是任意字母,但通常必须要大写。<t>通常需放在方法的返回值声明之前。例如: public static <t> void doxx(T t);
练习:
编写一个泛形方法,实现数组指定位置上元素的交换。
编写一个泛形方法,接收一个任意数组,并颠倒数组中的所有元素。
注意:
只有对象类型才能作为泛型方法的实际参数。
在泛型中可以同时有多个类型,例如:
public static <k> V getValue(K key) { return map.get(key);}
7.12 自定义泛形——泛型类
如果一个类多处都要用到同一个泛型,可以把泛形定义在类上(即类级别的泛型),语法格式如下:
public class GenericDao<t> {
private T field1;
public void save(T obj){}
public T getId(int id){}
}
注意,静态方法不能使用类定义的泛形,而应单独定义泛形。
package cn.itcast.generic;
//自定义带泛型的方法
public class Demo5 {
public void testa(){
a("aaaa");
}
public <t> void a(T t){
}
public <t> void b(T t,E e,K k){
}
} package cn.itcast.generic;
//自定义类上的泛型
public class Demo6 <t>{
public void testa(){
//a("aaaa");
}
public void a(T t){
}
public <e> void b(T t,E e,K k){
}
//类上的泛型不能作用于静态方法
public static <t>void c(T t){
}
}
7.13 泛型的高级应用——通配符
定义一个方法,接收一个集合,并打印出集合中的所有元素,如下所示:
void print (Collection<string> c) {
for (String e : c) {
System.out.println(e);
}
}
问题:该方法只能打印保存了Object对象的集合,不能打印其它集合。通配符用于解决此类问题,方法的定义可改写为如下形式:
void print (Collection> c) { //Collection>(发音为:"collection of unknown")
for (Object e : c) {
System.out.println(e);
}
}
此种形式下需要注意的是:由于print方法c参数的类型为Collection>,即表示一种不确定的类型,因此在方法体内不能调用与类型相关的方法,例如add()方法。
总结:使用?通配符主要用于引用对象,使用了?通配符,就只能调对象与类型无关的方法,不能调用对象与类型有关的方法。
7.14 泛型的高级应用——有限制的通配符
限定通配符的上边界:
正确:Vector<?extends Number> x = new Vector<integer>();
错误:Vector<?extends Number> x = new Vector<string>();
限定通配符的下边界:
正确:Vector<?super Integer> x = new Vector<number>();
错误:Vector<?super Integer> x = new Vector<byte>();
问题:以下代码行不行?
public void add(List extends String> list){
list.add("abc");
}
7.15 Annotation(注解) 概述
从 JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是 Annotation(注解)。
什么是Annotation,以及注解的作用?三个基本的 Annotation:
@Override: 限定重写父类方法, 该注解只能用于方法
@Deprecated: 用于表示某个程序元素(类, 方法等)已过时
@SuppressWarnings: 抑制编译器警告.
Annotation 其实就是代码里的特殊标记, 在Java技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么去运行类。
掌握注解技术的要点:
如何定义注解
如何反射注解
7.16 自定义Annotation
定义新的 Annotation 类型使用 @interface 关键字
声明注解的属性:
Annotation 的属性声明方式:String name();
Annotation 属性默认值声明方式:
String name() default “xxx”;
特殊属性value:如果注解中有一个名称为value的属性,那么使用注解时,可以省略value=部分,例如:@MyAnnotation(“xxx")。
7.17 JDK 的元Annotation
元 Annotation指修饰Annotation的Annotation。JDK中定义了如下元Annotation:
@Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留的域, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 通过这个变量指定域。
RetentionPolicy.CLASS: 编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注释. 这是默认值
RetentionPolicy.RUNTIME:编译器将把注释记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注释. 程序可以通过反射获取该注释
RetentionPolicy.SOURCE: 编译器直接丢弃这种策略的注释
@Target: 指定注解用于修饰类的哪个成员. @Target 包含了一个名为 value 的成员变量.
@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档.
@Inherited: 被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的 Annotation, 则其子类将自动具有该注解
7.18 提取Annotation 信息
JDK 5.0 在 java.lang.reflect 包下新增了 AnnotationElement 接口, 该接口代表程序中可以接受注释的程序元素
当一个 Annotation 类型被定义为运行时 Annotation 后, 该注释才是运行时可见, 当 class 文件被载入时保存在 class 文件中的 Annotation 才会被虚拟机读取
程序可以调用 AnnotationElement 对象的如下方法来访问 Annotation 信息
7.19 Tip:动态代理
在java里,每个对象都有一个类与之对应。
现在要生成某一个对象的代理对象,这个代理对象也要通过一个类来生成,所以首先要编写用于生成代理对象的类。
如何编写生成代理对象的类,两个要素:
代理谁
如何生成代理对象
代理谁?
设计一个类变量,以及一个构造函数,记住代理类代理哪个对象。
如何生成代理对象?
设计一个方法生成代理对象(在方法内编写代码生成代理对象是此处编程的难点)
Java提供了一个Proxy类,调用它的newInstance方法可以生成某个对象的代理对象,使用该方法生成代理对象时,需要三个参数:
1.生成代理对象使用哪个类装载器
2.生成哪个对象的代理对象,通过接口指定
3.生成的代理对象的方法里干什么事,由开发人员编写handler接口的实现来指定。
初学者必须理解,或不理解必须记住的2件事情:
Proxy类负责创建代理对象时,如果指定了handler(处理器),那么不管用户调用代理对象的什么方法,该方法都是调用处理器的invoke方法。
由于invoke方法被调用需要三个参数:代理对象、方法、方法的参数,因此不管代理对象哪个方法调用处理器的invoke方法,都必须把自己所在的对象、自己(调用invoke方法的方法)、方法的参数传递进来。
7.20 Tip:动态代理应用
在动态代理技术里,由于不管用户调用代理对象的什么方法,都是调用开发人员编写的处理器的invoke方法(这相当于invoke方法拦截到了代理对象的方法调用)。
并且,开发人员通过invoke方法的参数,还可以在拦截的同时,知道用户调用的是什么方法,因此利用这两个特性,就可以实现一些特殊需求,例如:拦截用户的访问请求,以检查用户是否有访问权限、动态为某个对象添加额外的功能。
7.21 类加载器
类加载器负责将 .class 文件(可能在磁盘上, 也可能在网络上) 加载到内存中, 并为之生成对应的 java.lang.Class 对象
当 JVM 启动时,会形成由三个类加载器组成的初始类加载器层次结构:
7.22 bootstrap classloader
bootstrap classloader:引导(也称为原始)类加载器,它负责加载Java的核心类。这个加载器的是非常特殊的,它实际上不是 java.lang.ClassLoader的子类,而是由JVM自身实现的。可以通过执行以下代码来获得bootstrap classloader加载了那些核心类库:
URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
for (int i = 0; i
元素类型可以是元素内容、或类型
如为元素内容:则需要使用()括起来,如
如为元素类型,则直接书写,DTD规范定义了如下几种类型:
EMPTY:用于定义空元素,例如<br><hr>
ANY:表示元素内容为任意类型。
元素内容中可以使用如下方式,描述内容的组成关系
元素内容使用空白符分隔,表示出现顺序没有要求: ×
用逗号分隔,表示内容的出现顺序必须与声明时一致。
用|分隔,表示任选其一,即多个只能出现一个
在元素内容中也可以使用+、*、?等符号表示元素出现的次数:
+: 一次或多次 (书+)
?: 0次或一次 (书?)
*: 0次或多次 (书*)
也可使用圆括号( )批量设置,例
7.27 Tip:属性定义
xml文档中的标签属性需通过ATTLIST为其设置属性
语法格式:
属性声明举例:
对应XML文件:
…商品>
…商品>
设置说明:
#REQUIRED:必须设置该属性
#IMPLIED:可以设置也可以不设置
#FIXED:说明该属性的取值固定为一个值,在 XML 文件中不能为该属性设置其它值。但需要为该属性提供这个值
直接使用默认值:在 XML 中可以设置该值也可以不设置该属性值。若没设置则使用默认值。
举例:
7.28 Tip:常用属性值类型
CDATA:表示属性值为普通文本字符串。
ENUMERATED
ID
ENTITY(实体)
7.29 Tip:属性值类型ENUMERATED
属性的类型可以是一组取值的列表,在 XML 文件中设置的属性值只能是这个列表中的某个值(枚举)
<?xml version = "1.0" encoding="GB2312" standalone="yes"?>
]>
购物篮>
7.30 Tip:属性值类型 ID
表示属性的设置值为一个唯一值。
ID 属性的值只能由字母,下划线开始,不能出现空白字符
7.31 Tip:实体定义
实体用于为一段内容创建一个别名,以后在XML文档中就可以使用别名引用这段内容了。
在DTD定义中,一条语句用于定义一个实体。
实体可分为两种类型:引用实体和参数实体。
7.32 Tip:实体定义引用实体
引用实体主要在 XML 文档中被应用
语法格式:
:直接转变成实体内容
引用方式:
&实体名称;
举例:
……
&copyright;
7.33 Tip:实体定义参数实体
参数实体被 DTD 文件自身使用
语法格式:
引用方式:
%实体名称;
举例1:
举例2:
...
7.34 Tip:XML解析技术概述
XML解析方式分为两种:dom和sax
dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式。
sax: (Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它。
XML解析器
Crimson、Xerces 、Aelfred2
XML解析开发包
Jaxp、Jdom、dom4j
7.35 Tip:JAXP
JAXP 开发包是J2SE的一部分,它由javax.xml、org.w3c.dom 、org.xml.sax 包及其子包组成
在 javax.xml.parsers 包中,定义了几个工厂类,程序员调用这些工厂类,可以得到对xml文档进行解析的 DOM 或 SAX 的解析器对象。
7.36 Tip:使用JAXP进行DOM解析
javax.xml.parsers 包中的DocumentBuilderFactory用于创建DOM模式的解析器对象 , DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供了一个newInstance方法 ,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。
7.37 Tip:获得JAXP中的DOM解析器
调用 DocumentBuilderFactory.newInstance() 方法得到创建 DOM 解析器的工厂。
调用工厂对象的 newDocumentBuilder方法得到 DOM 解析器对象。
调用 DOM 解析器对象的 parse() 方法解析 XML 文档,得到代表整个文档的 Document 对象,进行可以利用DOM特性对整个XML文档进行操作了。
package cn.itcast.xml;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.junit.Test;
import org.w3c.dom.Document;
public class Demo2 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//1.创建工厂
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
//2。得到dom解析器
DocumentBuilder builder=factory.newDocumentBuilder();
//3。解析xml文档,得到代表文档的document
Document document=builder.parse("src/book.xml");
}
}
<?xml version="1.0" encoding="UTF-8"?>java web就业书名>
张孝祥作者>
40售价>
书>
C++教程书名>
自己作者>
50售价>
书>
书架>
package cn.itcast.xml;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
//使用dom方式对xml文档进行CRUD
public class Demo3 {
//读取C++教程书名>
public void read1() throws Exception
{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("src/book.xml");
NodeList list=document.getElementsByTagName("书名");
Node node=list.item(1);
String content=node.getTextContent();
System.out.println(content);//C++教程
}
//得到文档中所有标签
public void read2() throws Exception
{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("src/book.xml");
NodeList list=document.getElementsByTagName("书名");
Node root=document.getElementsByTagName("书架").item(0);
list(root);
}
private void list(Node node) {
Node child;
if (node instanceof Element)
System.out.println(node.getNodeName());
NodeList nodelist=node.getChildNodes();
for (int i=0;i<nodelist.getlength child="nodelist.item(i);" list name="xxxx">java web就业书名>
public void read3() throws Exception
{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("src/book.xml");
NodeList list=document.getElementsByTagName("书名");
Node node=list.item(0);
if(node.hasAttributes()){
NamedNodeMap nodemap=node.getAttributes();
for(int i=0;i<nodemap.getlength node nd="nodemap.item(i);" string strname="nd.getNodeName();" strval="nd.getNodeValue();" system.out.println element node2="(Element)list.item(0);" str3='node2.getAttribute("name");'>10售价>
public void add() throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("src/book.xml");
//创建节点
Element price=document.createElement("售价");
price.setTextContent("59.0元");
//把创建的节点放到第一本书上
document.getElementsByTagName("书").item(0).appendChild(price);
//把跟新后的内容写回文档
Transformer transformer=TransformerFactory.newInstance().newTransformer();
DOMSource source=new DOMSource(document);
FileOutputStream outstream =new FileOutputStream(new File("src/outbook.xml"));
StreamResult reslut=new StreamResult(outstream);
transformer.transform(source, reslut);
outstream.close();
}
//向文档中指定位置上添加节点 10售价>
public void add2() throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("src/book.xml");
//创建节点
Element price=document.createElement("售价");
price.setTextContent("59.0元");
//得到参考节点
Element refNode=(Element)document.getElementsByTagName("售价").item(0);
//得到挂崽的节点
Element book=(Element)document.getElementsByTagName("书").item(0);
//把创建的节点放到第一本书上
document.getElementsByTagName("书").item(0).appendChild(price);
// 往book节点指定位置插值
book.insertBefore(price, refNode);
Transformer transformer=TransformerFactory.newInstance().newTransformer();
DOMSource source=new DOMSource(document);
FileOutputStream outstream =new FileOutputStream(new File("src/outbook2.xml"));
StreamResult reslut=new StreamResult(outstream);
transformer.transform(source, reslut);
outstream.close();
}
//向文档节点 添加属性 10售价>
public void addAtt() throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("src/book.xml");
//得到参考节点
Element refNode=(Element)document.getElementsByTagName("售价").item(0);
refNode.setAttribute("addAtrr","new cha ru value");
Transformer transformer=TransformerFactory.newInstance().newTransformer();
DOMSource source=new DOMSource(document);
FileOutputStream outstream =new FileOutputStream(new File("src/outbook3.xml"));
StreamResult reslut=new StreamResult(outstream);
transformer.transform(source, reslut);
outstream.close();
}
//删除 10售价>
public void delete() throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("src/book.xml");
//得到要删除的节点
Element refNode=(Element)document.getElementsByTagName("售价").item(0);
refNode.getParentNode().removeChild(refNode);
Transformer transformer=TransformerFactory.newInstance().newTransformer();
DOMSource source=new DOMSource(document);
FileOutputStream outstream =new FileOutputStream(new File("src/outbook3.xml"));
StreamResult reslut=new StreamResult(outstream);
transformer.transform(source, reslut);
outstream.close();
}
//更新 售价
public void update() throws Exception{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse("src/book.xml");
//得到要更新的节点
Element refNode=(Element)document.getElementsByTagName("售价").item(0);
refNode.setTextContent("1000");
Transformer transformer=TransformerFactory.newInstance().newTransformer();
DOMSource source=new DOMSource(document);
FileOutputStream outstream =new FileOutputStream(new File("src/outbook3.xml"));
StreamResult reslut=new StreamResult(outstream);
transformer.transform(source, reslut);
outstream.close();
}
}
7.38 调虚拟机内存大小
-Xmx83886080 C:\Program Files\Java\jdk1.7.0\docs\technotes\tools\windows\java.html
-Xmx81920k
-Xmx80m
7.39 Tip:DOM编程
DOM模型(document object model)
DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
在dom中,节点之间关系如下:
位于一个节点之上的节点是该节点的父节点(parent)
一个节点之下的节点是该节点的子节点(children)
同一层次,具有相同父节点的节点是兄弟节点(sibling)
一个节点的下一个层次的节点集合是节点后代(descendant)
父、祖父节点及所有位于节点上面的,都是节点的祖先(ancestor)
节点类型(下页ppt)
Node对象提供了一系列常量来代表结点的类型,当开发人员获得某个Node类型后,就可以把Node节点转换成相应的节点对象(Node的子类对象),以便于调用其特有的方法。(查看API文档)
Node对象提供了相应的方法去获得它的父结点或子结点。编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容了。
7.40 Tip:DOM方式解析XML文件
DOM解析编程
遍历所有节点
查找某一个节点
删除结点
更新结点
添加节点
7.41 Tip:更新XML文档
javax.xml.transform包中的Transformer类用于把代表XML文件