xml、网络编程、 反射
XML
常用于配置文件、传输数据。
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="p001">
<name>张三</name>
</person>
</persons>
xml文档必须以<?xml 开头 以?>结束;
version 指定xml文档版本,encoding指定当前文档的编码,默认是utf-8;
元素:元素区分大小写,不能使用空格,不能使用冒号:,必须只有一个根元素 <persons>
属性:属性是元素的一部分,一个元素可以有N个属性,不可以同名,不能使用空格冒号等特殊字符,以字母开头。 id="p001"
注释:<!--xml注释 -->
转义字符
<小于 >大于 " 等
CDATA区
<![CDATA[
任意内容 代码之类的
]]>
<![CDATA[
if(a>b && b<c){
if....
}
]]>
DTD约束文档
文档类型定义,用来约束XML文档,规定XML文档中元素的名称,子元素的名称及顺序,元素的属性等。
DTD语法
<!ELEMENT web-app (servlet*,servlet-mapping*,welcome-file-list?) >
web-app 包括3个元素,且必须顺序出现。
servlet 子标签个数任意
servlet-mapping 子标签个数任意
welcome-file-list 子标签最多只能出现一次
? 表示该对象可以出现,但只能出现一次
* 表示该对象允许出现任意多次,也可以是零次
+ 表示该对象最少出现一次,可以出现多次
() 用来分组
| 出现的对象中选择一个 (man | women)
, 表式对象必须按指定的顺序出现 (a,b,b)
DTD约束
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app SYSTEM "web-app_2_3.dtd">
<web-app>
<context-param>
<param-name></param-name>
<param-value></param-value>
</context-param>
</web-app>
引入约束后 按照 约束格式书写xml
Schema约束
Schema是新的xml文档约束,要比DTD强大很多,是DTD替代者。
Schema扩展名是xsd,而不是xml. 支持名称空间。
Schema扩展名是xsd,而不是xml. 支持名称空间。
XML解析
https://dom4j.github.io/
使用dom4j 可以创建、修改、读取XML文件。
SAXReader reader = new SAXReader();
Document document = reader.read("src/hh.xml");
// 根节点
Element root = document.getRootElement();
//获取属性的值
String version = root.attributeValue("version");
System.out.println("Version:"+version);
List<Element> allChildElement = root.elements();
for(Element child : allChildElement){
String childName = child.getName();
System.out.println(childName);
if("head".equals(childName)){
Element title = child.element("title");
String titleTxt = title.getText();
System.out.println(titleTxt);
}
}
网络通信协议
有两种TCP/IP 协议和UDP 协议,常用的是TCP/IP协议。
UDP协议:无连接通信协议,数据发送端和接受端不需要建立网络连接。如果接受端不在收不到,无法保证数据完整性。如:发短信不用考虑对方在不在线。数据限制在64kb以内。
TCP协议:面向连接的通信协议,数据发送端和接受端需要建立网络连接。在TCP连接中必须要明确客户端与服务器端,由客户端向服务器端发出连接请求,每次连接的出啊过年就爱你都需要经过三次握手,cs->bs请求 bs->cs回应 cs->bs再次请求 确认连接。如:打电话 需要双方在线。数据完整,适合大数据传输。
IP地址
每台电脑的地址, 192.168 局域网 127.0.0.1 本机
端口号 一个地址多个端口 对应不同程序
InetAddress类
InetAddress.getLocalHost() //本地主机地址 192.168.20.104
UDP发送
public static void UDPSend() throws IOException {
//要发送的数据
byte [] data = "你好UDP".getBytes();
//发送的目标
InetAddress inet = InetAddress.getByName("127.0.0.1");
//6000是端口号
DatagramPacket dp = new DatagramPacket(data,data.length,inet,6000);
DatagramSocket ds = new DatagramSocket();
ds.send(dp);
ds.close();
}
UDP接收
public static void UDPReceive() throws IOException{
DatagramSocket ds = new DatagramSocket(6000);
byte [] bytes = new byte [1024];
DatagramPacket dp = new DatagramPacket(bytes,bytes.length);
ds.receive(dp);
System.out.println(new String(bytes));
ds.close();
}
TCP 在JDK中 两个类用于实现TCP程序,一个是ServerSocket服务端 ,另一个是 Socket客户端。 服务器端不会主动连接客户端。
服务器端
ServerSocket ss = new ServerSocket(8888);
//监听
Socket socket = ss.accept();
InputStream in = socket.getInputStream();
byte[] data = new byte[1024];
int len = in.read(data);
System.out.println(new String(data,0,len));
//服务器向客户端发送
OutputStream ot = socket.getOutputStream();
ot.write("服务器收到了".getBytes());
ot.close();
socket.close();
ss.close();
客户端
//创建socket对象 连接服务器
Socket socket = new Socket("127.0.0.1",8888);
OutputStream out = socket.getOutputStream();
out.write("TCP发送".getBytes());
out.close();
//获取服务器响应
InputStream in = socket.getInputStream();
byte[] bytes = new byte[1024];
int len = in.read(bytes);
System.out.println(new String(bytes,0,len));
类加载器
当程序要使用某个类时,如果该类还没加载到内存中,要经过加载,连接,初始化三步来对这个类进行初始化。
加载:将class文件读入内存中,创建一个class对象。
连接:检验是否有正确的内部结构,将静态成员分配内存,并设置初始化值。
初始化:初始化对象 new对象
通俗的讲就是把.class文件加载到内存里,并把这个.class文件封装成一个Class类型的对象。
Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载 比如System、String等,在JDK中JRE的lib目录下rt.jar文件中
Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载,JDK中JRe的lib目录下ext目录
System ClassLoader 系统类加载器
负责在JVM启动时加载来自Java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
反射
Java反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法。对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Class类
Class类没有构造方法,Class对象实在加载类时由Java虚拟机以及通过调用类加载器中的defineclass方法自动构造的。
得到class对象
方法一:通过对象获取
Person p = new Person();
Class cls = p.getClass();
方法二:通过类名获取
Class cls = Person.class;
方法三:Class方法获取
Class cls = Class.forName("Person") //CLassNotFOundException
通过反射获取无参构造方法并使用
Class cls = Main.class;
//返回无参构造函数
Constructor con = cls.getConstructor();
//运行获取到的构造方法
Object obj = con.newInstance();
通过反射获取有参构造方法并使用
Class cls = Person.class;
//传入相应的参数列表
Constructor con = cls.getConstructor(String.class,Integer.class)
//运行获取到的有参构造方法
Object obj = con.newInstance("zhangsan",18);
通过反射获取又遭方法并运行的快速方式
Class cls = Person.class;
Object obj = cls.newInstrance(); //无参构造方法
反射获取私有构造方法并使用
Class cls = Person.class;
//返回包含私有的构造方法
Constructor con = cls.getDeclaredConstructor(Integer.class);
//获取私有的
con.setAccessible(true);
Object obj = con.newInstance(18);
反射获取成员变量并改值
Class cls = Person.class;
//获取成员变量
Field filed = cls.getField("name");
Object obj = cls.newInstrance();
//赋值
filed.set(obj,"libai");
反射获取成员方法 无参并运行
Class cls = Main.class;
Object obj = cls.newInstance();
Method m = cls.getMethod("sayHi");
//运行获取到的方法
m.invoke(obj);
反射获取成员方法 有参并执行
Class cls = Main.class;
Object obj = cls.newInstance();
Method m = cls.getMethod("sayHi",String.class);
m.invoke(obj,"david")
反射泛型擦除
在String泛型中加integer类型的数据
ArrayList<String> array = new ArrayList<String>();
array.add("a");
//编译器会报错
//array.add(1);
//反射方式,添加int类型
Class c = array.getClass();
Method method = c.getMethod("add", Object.class);
method.invoke(100);
System.out.println(array);
反射通过配置文件来决定运行的步骤
FileReader r = new FileReader("config.properties");
Properties pro = new Properties();
pro.load(r);
r.close();
String className = Pro.getProperty("className");
String methodName = pro.getProperty("methodName");
Class c = Class.forName(className);
Object obj = c.newInstance();
Method method = c.getMethod(methodName);
method.invoke(obj):
className=Person
methodName=sayHi