day17_0714课堂笔记
程序员文章站
2024-03-21 23:01:28
...
day17_0714课堂笔记
1、IO流回顾
反射的分类:
按流向分为:输入流和输出流。
按功能分为:节点流和功能流。
按操作单元分为:字节流和字符流。
节点流:
节点:InputStream OutputStream FileInputStream–>真实做读入写出。
功能:
缓冲流: 加快读写效率,->用到字节或者字符的节点流,就在外面包含一个缓冲流。
转换流: InputStreamReader(字节节点)。
data流: DataInputStream(字节节点流)–>读写数据并保存数据的类型(基本数据类型+String)。
Object流: ObjectInputStream(字节节点流))–>基本数据类型+对象类型。
2、作业讲解
客服端
package com.wse.net01;
import java.io.*;
import java.net.Socket;
/**
* 多用户登入
*/
public class TCPClient01 {
public static void main(String[] args) throws IOException {
System.out.println("=============客户端=================");
//创建客户端
Socket client = new Socket("localhost",8888);
//将系统输入流转换为字符流
//Scanner s = new Scanner(System.in);
BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
System.out.print("请输入用户名:");
//readLine()为BufferedReader的方法,上面不能用Reader r;
String name = r.readLine();
System.out.print("请输入密码:");
String pwd = r.readLine();
//获取流,操作字符串,将客户端获取的字节输出流
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
out.writeUTF("name="+name+"&"+"pwd="+pwd);
out.flush();
//获取服务端的响应
DataInputStream in = new DataInputStream(new BufferedInputStream(client.getInputStream()));
String result = in.readUTF();
System.out.println(result);
//关闭
in.close();
out.close();
client.close();
}
}
服务端
package com.wse.net01;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer02 {
public static void main(String[] args) throws IOException {
System.out.println("=============服务端===================");
//创建服务端
ServerSocket server = new ServerSocket(8888);
boolean flag = true;
while (flag) {
//阻塞式监听
Socket client = server.accept();
System.out.println("获取客户端成功");
//创建客户端线程
new Thread(new Login(client)).start();
}
//关闭服务端
server.close();
}
static class Login implements Runnable {
private Socket client = null;
private DataInputStream in = null;
DataOutputStream out = null;
//构造方法,创建流
public Login(Socket client) {
this.client = client;
try {
in = new DataInputStream(new BufferedInputStream(client.getInputStream()));
out = new DataOutputStream(new BufferedOutputStream(client.getOutputStream()));
} catch (IOException e) {
e.printStackTrace();
}
}
//读取数据
public String read() {
String msg = null;
try {
msg = in.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
//判断并写出数据
public void write(String msg) {
String name = "";
String pwd = "";
//操作数据
String[] s1 = msg.split("&");
for (String str : s1) {
String[] s2 = str.split("=");
if ("name".equals(s2[0])) {
name = s2[1];
} else {
pwd = s2[1];
}
}
try {
out.writeUTF(("laopei".equals(name) && "0523".equals(pwd)) ? "登入成功" : "登入失败");
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
//关闭流
public void close() {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (client != null) {
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
//读取数据
String mesage = read();
//输出结果
write(mesage);
//关闭流
close();
}
}
}
3、反射
3.1反射的概念及方法
“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”,如Python,Ruby是动态语言;显然C++,Java,C#不是动态语言,但是JAVA有着一个非常突出的动态相关机制:Reflection。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
常用方法:
static Class<?> forName(String className)
返回与带有给定字符串名的类或接口相关联的 Class 对象。
Class<? super T> getSuperclass()
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
Class<?>[] getInterfaces()
确定此对象所表示的类或接口实现的接口。
int getModifiers()
返回此类或接口以整数编码的 Java 语言修饰符。
String getName()
以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。
Package getPackage()
获取此类的包。
String getSimpleName()
返回源代码中给出的底层类的简称。
Constructor<T> getConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Constructor<?>[] getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
Constructor<?>[] getDeclaredConstructors()
返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
Method getMethod(String name, Class<?>... parameterTypes)
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
Method[] getMethods()
返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
Method getDeclaredMethod(String name, Class<?>... parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
Method[] getDeclaredMethods()
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Field getField(String name)
返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
Field[] getFields()
返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
Field getDeclaredField(String name)
返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
Field[] getDeclaredFields()
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。
T newInstance()
创建此 Class 对象所表示的类的一个新实例。
3.2获取Class的三种方式
- 1 任意类型.class
- 2 引用.class
- 3 Class.forname(完整包名带类名)
package com.wse.reflect02;
import java.util.Arrays;
/**
* 获取class的三种方式
*/
public class ReflectDemo02 {
public static void main(String[] args) {
//1 任意类型.class
Class c = String.class;
System.out.println(c);//class java.lang.String
//2 引用.class
Class c1 = "aaa".getClass();
System.out.println(c1);//class java.lang.String
try {
//3 Class.forname(完整包名带类名)
Class c2 = Class.forName("java.lang.String");
System.out.println(c2);//class java.lang.String
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//getSuperclass() 获取当前Class对象所表示类型的父类的Class对象
Class c3 = c.getSuperclass();
System.out.println(c3);//class java.lang.Object
//getInterfaces() 获取当前Class对象所表示类型的父接口的Class对象数据
Class[] c4 = c.getInterfaces();
System.out.println(Arrays.toString(c4));//[interface java.io.Serializable, interface java.lang.Comparable, interface java.lang.CharSequence]
//获取基本数据类型的Class对象 包装类.TYPE=基本类型
Class c5 = int.class;
Class c6 = Integer.class;
System.out.println(c5);//int
System.out.println(c6);//class java.lang.Integer
System.out.println(c5==Integer.TYPE);//true
}
}
3.3Java反射可实现的功能
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法;
- 生成动态代理
3.4可变参数
可变参数:
- 参数个数可以为0~多个,要求类型相同,个数可变
- 数据类型 … 参数名 -->可变参数
-
如果存在多个 参数,可变参数必须在参数列表的最后
-
在方法的内部,把可变参数当做数组使用
3.5通过反射创建对象
- Class类的newInstance() -->不推荐使用,默认调用空构造,没有就无法使用。
- Constructor类提供的newInstance(Object… initargs)方法创建对象,调用当前的构造器初始化信息。
public class ReflectDemo04 {
public static void main(String[] args) throws Exception {
Class c = Person.class;
constructorTest(c);
//methodTest(c);
//fieledTest(c);
}
public static void constructorTest(Class<Person> c) throws Exception {
//获取Person的无参构造
Constructor<Person> con = c.getConstructor();
//创建对象
Person person = con.newInstance();
//打印对象
System.out.println(person);//Person{name='null', age=0, sex='null', id=0, country='null'}
//获取Person的一个公共的构造器
Constructor<Person> con1 = c.getConstructor(String.class, Integer.TYPE, Integer.TYPE);
//创建对象
Person person1 = con1.newInstance("聂兵", 18, 1001);
//打印对象
System.out.println(person1);//Person{name='聂兵', age=18, sex='null', id=1001, country='null'}
//获取所有构造器
Constructor[] cons = c.getDeclaredConstructors();
for (Constructor con2 : cons) {
System.out.println(con2);
}
//获取私有构造器
Constructor<Person> con3 = c.getDeclaredConstructor(String.class, Integer.TYPE, String.class);
//放开权限
con3.setAccessible(true);
//创建对象
Person person2 = con3.newInstance("聂兵", 18, "男");
System.out.println(person2);//Person{name='聂兵', age=18, sex='男', id=0, country='null'}
//关闭权限
con3.setAccessible(false);
}
}
3.6反射操作方法
public class ReflectDemo04 {
public static void main(String[] args) throws Exception {
Class c = Person.class;
//constructorTest(c);
methodTest(c);
//fieledTest(c);
}
/*
* 反射操作方法
* 1.获取方法
* 方法 getDeclaredMethod(String name, 类<?>... parameterTypes)
方法[] getDeclaredMethods()
方法 getMethod(String name, 类<?>... parameterTypes)
方法[] getMethods()
* 2.调用方法
* Object invoke(Object obj, Object... args)
*/
public static void methodTest(Class<Person> c) throws Exception {
Person person = c.newInstance();
// Method[] getDeclaredMethods()
//返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,
// 包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Method[] declaredMethods = c.getDeclaredMethods();
for (Method m : declaredMethods) {
System.out.println(m);
}
//Method getMethod(String name, Class<?>... parameterTypes) 获取类中某个公共的方法
//返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
Method getName = c.getMethod("getName");
Method setName = c.getMethod("setName", String.class);
//调用公共方法
Object invoke1 = setName.invoke(person, "wse");
String name = (String) getName.invoke(person);
System.out.println(name);
// Method getDeclaredMethod(String name, Class<?>... parameterTypes)
// 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
//获取静态方法
Method sleep = c.getDeclaredMethod("sleep");
//调用方法
sleep.invoke(person);//我困了
//获取私有方法
Method sleepSecretly = c.getDeclaredMethod("sleepSecretly");
//放开权限
sleepSecretly.setAccessible(true);
sleepSecretly.invoke(person);//我上课偷偷睡觉
//关闭权限
sleepSecretly.setAccessible(false);
}
}
3.7反射操作属性
public class ReflectDemo04 {
public static void main(String[] args) throws Exception {
Class c = Person.class;
//constructorTest(c);
//methodTest(c);
fieledTest(c);
}
/*
* 反射操作属性
* Field getField(String name)
返回一个 Field指定对象,反映了公共成员的这个 类对象所表示的类或接口。
Field[] getFields()
Field getDeclaredField(String name)
返回一个 Field指定对象,反映了宣布的这个 类对象所表示的类或接口。
Field[] getDeclaredFields()
void set(Object obj, Object value) 设置值
get(Object obj) 获取值
*/
public static void fieledTest(Class<Person> c) throws Exception {
//创建对象
Person person = c.newInstance();
//获取对象的属性
Field name = c.getDeclaredField("name");
System.out.println("name = " + name);//name = private java.lang.String com.wse.bean.Person.name
//开放权限
name.setAccessible(true);
//修改属性数据
name.set(person,"wse");
System.out.println(person);//Person{name='wse', age=0, sex='null', id=0, country='null'}
System.out.println(name.get(person));//wse
//关闭权限
name.setAccessible(false);
Field id = c.getDeclaredField("id");
//不在同包下除public修饰的属性都需要打开权限
id.setAccessible(true);
System.out.println(id.get(person));//0
//获取静态属性
Field country = c.getDeclaredField("country");
country.setAccessible(true);
System.out.println(country.get(person));
}
上一篇: 使用生成器创建新的迭代模式
下一篇: 笔试记录