目录
一、反射
1、ReflexDemo1
package com.shujia.lhw.day27;
import com.shujia.lhw.day24.Person;
/*
反射:通过一个Class文件对象去使用改文件对象中的成员变量,构造方法,成员方法
我们之前去使用成员的时候,现有一个java文件,然后在实例化的时候,直接new就完事了
Person p = new Person();
p.eat();
总归来说底层还是依赖一个class文件
也就是需要先得到一个Class文件对象
class类:
成员变量:Field
构造方法:Constructor
成员方法:Method
如何获取一个类对应的Class文件对象呢?
1、通过Object类中的getClass()方法,返回此Object的运行时类
2、在不new对象的前提下,获取该类的class文件对象,使用类的静态属性class来获取
*/
public class ReflexDemo1 {
public static void main(String[] args) {
//方式1:通过Object类中的getClass()方法,返回Object的运行时类
Person p = new Person();
Class<?extends Person> c1 = p.getClass();
Person p2 = new Person();
Class<? extends Person> c2 = p.getClass();
System.out.println(c1==c2);
//方式2:在不new对象的前提下,获取该类的class文件对象,使用类的静态属性class来获取
Class<Person> c3 = Person.class;
System.out.println(c1==c3);
System.out.println(c2==c3);
//方式3:public static Class<?> forName(String className)
//返回与给定字符串名称的类或接口相关联的类对象。调用其方法相当于:
Class<?> c4 = null;
try {
c4 = Class.forName("com.shujia.lhw.day27.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c1==c4);
System.out.println(c2==c4);
}
}
package com.shujia.lhw.day27;
public class Person {
//成员变量
private String name;
int age;
protected String address;
public String id;
//构造方法
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
//成员方法
public void fun1(){
System.out.println("这是公共的方法fun1");
}
private void fun2(String s){
System.out.println("这是私有的方法fun2"+s);
}
protected void fun3(){
System.out.println("这是被保护的fun3");
}
void fun4(){
System.out.println("这是默认修饰符的方法fun4");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", id='" + id + '\'' +
'}';
}
}
2、ReflexDemo2
package com.shujia.lhw.day27;
import java.lang.reflect.Constructor;
/**
如何通过反射获取Class文件对象中的构造方法并使用呢?
*/
public class ReflexDemo2 {
public static void main(String[] args) throws Exception{
//获取Class文件对象
Class<?> c1 = Class.forName("com.shujia.lhw.day27.Person");
//获取构造方法,只能获取所有的公共的构造方法
//public Constructor<?>[] getConstructors()
//返回一个包含Constructor对象的数组
Constructor<?>[] cons = c1.getConstructors();
for (Constructor c : cons) {
System.out.println(c);
}
System.out.println("=======================================");
//public Constructor<?>[] getDeclaredConstructors()
//返回反映Constructor对象表示的类声明的所有Constructor对象的数组类
//获取所有的构造方法,包括斯有,被保护的,默认的,公共的
Constructor<?>[] cons2 = c1.getConstructors();
for (Constructor<?> c : cons) {
System.out.println(c);
}
System.out.println("=======================================");
//获取单个构造方法
//public Constructor<T> getConstructor(类<?>...parameterTypes)
//返回一个Constructor对象,该对象反映Constructor对象表示的类指定的公共函数
// Constructor<?> con = c1.getConstructor();//相当于获取无参构造方法
// System.out.println(con);
Constructor<?> con = c1.getConstructor(String.class);
System.out.println(con);
// Constructor<?> con = c1.getConstructor(String.class,int.class);
// System.out.println(con);
System.out.println("========================================");
//public T newInstance(Object..initargs)
//使用由此Constructor对象表示的构造函数,使用指定的初始化参数创建和初始化构造函数的声明类的新实例
// Object o = con.newInstance("你好",23);
// System.out.println(o);
Person p = (Person)con.newInstance("1001");
System.out.println(p);
}
}
3、ReflexDemo3
package com.shujia.lhw.day27;
import java.lang.reflect.Constructor;
/**
* 通过反射获取私有的构造方法并创建对象
*
*/
public class ReflexDemo3 {
public static void main(String[] args) throws Exception{
//获取类的字节码文件对象
Class<?> c1 = Class.forName("com.shujia.lhw.day27.Person");
//获取私有的构造方法
Constructor<?> con = c1.getDeclaredConstructor(String.class,int.class);
System.out.println(con);
//IIIegalAccessException非法的访问异常
//暴力访问
con.setAccessible(true);//这里的值如果是true的话,表示反射的对象在使用的时候取消Java语言的访问检查
//使用Constructor类中的方法来创建
Object o = con.newInstance("明旺",18);
Person p = (Person) o;
System.out.println(p);
}
}
4、ReflexDemo4
package com.shujia.lhw.day27;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/*
通过反射获取成员变量并使用
*/
public class ReflexDemo4 {
public static void main(String[] args) throws Exception{
//1、获取字节码文件对象
Class<?> c1 = Class.forName("com.shujia.lhw.day27.Person");
//获取所有的公共成员变量
//public Filed[] getFields()
//返回包含一个数组Field对象反射由此表示的类或接口的所有可以访问的公共字段类对象
Field[] fields = c1.getFields();
for(Field f : fields){
System.out.println(f);
}
System.out.println("=====================================");
//public Field[] getDeclaredFields()
//获取当前类中所有成员变量
//返回的数组Field对象反映此表示的类或接口声明的所有字段类对象
//这包括公共,受保护,默认(包)访问和私有字段,但不包括继承的字段
Field[] fields2 = c1.getDeclaredFields();
for(Field f : fields2){
System.out.println(f);
}
System.out.println("==========================================");
//获取无参构造方法,然后利用反射给成员变量赋值
Constructor<?> con = c1.getConstructor();
//创建对象
Object o = con.newInstance();
System.out.println(o);
System.out.println("============================================");
//获取单个成员变量
Field id = c1.getField("id");
//将指定对象上的成员变量赋上一个新的值
//void set(Object obj,Object value)
//将指定对象参数上的此Field对象表示的字段设置为指定的新值
id.set(o,"1002");
System.out.println(o);
System.out.println("===========================================");
//反射获取私有的成员变量并赋值
//NoSuchFieldException
// Field name = c1.getField("name");
// System.out.println(name);
Field name = c1.getDeclaredField("name");
System.out.println(name);
//暴力访问
name.setAccessible(true);
name.set(o,"王宇");
System.out.println(o);
System.out.println("============================================");
//获取被protected修饰的成员变量,不需要暴力访问
Field address = c1.getDeclaredField("address");
address.set(o,"安徽合肥");
System.out.println(o);
System.out.println("============================================");
//获取默认的修饰符修饰的成员变量并赋值,不需要暴力访问
Field age = c1.getDeclaredField("age");
age.set(o,19);
System.out.println(o);
}
}
5、ReflexDemo5
package com.shujia.lhw.day27;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/*
通过反射获取成员方法并使用
*/
public class ReflexDemo5 {
public static void main(String[] args) throws Exception{
//1、获取字节码文件对象
Class<?> c1 = Class.forName("com.shujia.lhw.day27.Person");
//获取方法
//public 方法[] getMethods()
//获去本类中的公共方法和父类中的所有的公共方法
//返回包含一个数组方法对象反射由此表示的类或接口的所有公共方法类对象,包括那些由类或接口和那些从超类和长接口继承的声明
Method[] methods = c1.getMethods();
for(Method m : methods){
System.out.println(m);
}
System.out.println("============================================");
Method[] methods2 = c1.getDeclaredMethods();
//获取自己的所有的方法,包括私有,不能获取父类的
for(Method m : methods2){
System.out.println(m);
}
System.out.println("=============================================");
//获取单个方法并调用
Method fun1 = c1.getMethod("fun1");
Constructor<?> cons = c1.getConstructor();
Object o = cons.newInstance();
//public Object invoke(Object obj,Object... args)
//在具有指定参数的方法对象上调用此方法对象表示的基础方法
//第一个参数指的是调用方法的对象,第二个参数指的是实际需要传入的数据(实参)
fun1.invoke(o);
System.out.println("=============================================");
// Method fun2 = c1.getMethod("fun2",String.class);
// System.out.println(fun2);
Method fun2 = c1.getDeclaredMethod("fun2",String.class);
//暴力访问
fun2.setAccessible(true);//只有私有的方法调用需要暴力访问
fun2.invoke(o,"数加科技");
System.out.println("==============================================");
Method fun3 = c1.getDeclaredMethod("fun3");
Object invoke = fun3.invoke(o);
System.out.println("==============================================");
Method fun4 = c1.getDeclaredMethod("fun4");
fun4.invoke(o);
}
}
6、ReflexTest1
package com.shujia.lhw.day27;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* 通过配置文件运行类的方法
*
* 配置文件:
* 配置文件里面基本上都是键--值这样的键值存在的
* <name>className</name>
* <value>com.shujia.lhw.day27.Person</value>
*/
public class ReflexTest1 {
public static void main(String[] args) throws Exception{
//在学习反射之前
// Person person = new Person();
// person.fun1();
// person.fun2();
//学习反射之后
Properties prop = new Properties();
FileReader fr = new FileReader("D:\\IdeaProjects\\bigdata15\\src\\com\\shujia\\lhw\\day27\\configure");
prop.load(fr);
fr.close();
//获取数据
String className = prop.getProperty("className");
System.out.println(className);
String methodName = prop.getProperty("methodName");
System.out.println(methodName);
//通过反射实现
Class<?> c1 = Class.forName(className);
Constructor<?> cons = c1.getConstructor();
Object o = cons.newInstance();
//通过反射调用方法
Method fun2 = c1.getDeclaredMethod(methodName,String.class);
//暴力访问
fun2.setAccessible(true);
fun2.invoke(o,"数加科技,yyds");
}
}
7、ReflexTest2
package com.shujia.lhw.day27;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 我给你ArrayList<Integer>的一个对象,我想在这个集合中添加已给字符串数据,如何实现呢?
*
*/
public class ReflexTest2 {
public static void main(String[] args) throws Exception{
ArrayList<Integer> list = new ArrayList<>();
// list.add(10);
// list.add("你好");
//通过反射实现
Class<? extends ArrayList> listClass = list.getClass();
Method add = listClass.getMethod("add", Object.class);
add.invoke(list,20);
add.invoke(list,"你好");
add.invoke(list,12.34);
// for(Integer i : list){
// System.out.println(i);
// }
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
Object next = (Object) iterator.next();
System.out.println(next);
}
}
}
8、ToolTest
package com.shujia.lhw.day27;
public class ToolTest {
public static void main(String[] args) {
//创建一个对象
Person person = new Person();
// person.name="小虎";
Tool tool = new Tool();
tool.setProperty(person,"name","小虎");
tool.setProperty(person,"age",18);
tool.setProperty(person,"address","安徽合肥");
tool.setProperty(person,"id","1003");
System.out.println(person);
}
}
package com.shujia.lhw.day27;
import java.lang.reflect.Field;
/*
public void setProperty(Object obj,String propertyName,Object value){}
此方法可将obj对象中名为propertyName的属性的值设置为value
*/
public class Tool {
public void setProperty(Object obj,String propertyName,Object value){
//通过反射来做
//通过对象获取到对应的字节码文件对象
Class<?> c = obj.getClass();
//通过字节码文件对象获取对应的成员变量形成的一个对象
try {
Field propertyName1 = c.getDeclaredField(propertyName);
//暴力访问
propertyName1.setAccessible(true);
//赋值
try {
propertyName1.set(obj,value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
package com.shujia.lhw.day27;
public class Person {
//成员变量
private String name;
int age;
protected String address;
public String id;
//构造方法
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
//成员方法
public void fun1(){
System.out.println("这是公共的方法fun1");
}
private void fun2(String s){
System.out.println("这是私有的方法fun2"+s);
}
protected void fun3(){
System.out.println("这是被保护的fun3");
}
void fun4(){
System.out.println("这是默认修饰符的方法fun4");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", id='" + id + '\'' +
'}';
}
}
二、动态代理
1、UserDemo
package com.shujia.lhw.day27;
public class UserDemo {
public static void main(String[] args) {
UserDaoImpl userDao = new UserDaoImpl();
userDao.add();
userDao.delete();
userDao.update();
userDao.select();
System.out.println("=======================================");
//真实的需求开发中不应该这么简单的操作就结束了
//通常这些操作之前应该有一个权限校验的步骤,不是任何人都能操作的
//操作完后应该留下一些日志信息,方便回溯
//通过分析并改进代码后,虽然实现了我们想要的功能
//但是呢,扩展性很差
//假设现在还有一个学生类,教师类也拥有增删改查的操作,怎么办呢
StudentDaoImpl studentDao = new StudentDaoImpl();
studentDao.login();
studentDao.regist();
}
}
package com.shujia.lhw.day27;
public class UserDaoImpl implements UserDao{
@Override
public void add() {
// System.out.println("权限校验");
System.out.println("增加数据");
// System.out.println("日志记录");
}
@Override
public void delete() {
// System.out.println("权限校验");
System.out.println("删除数据");
// System.out.println("日志记录");
}
@Override
public void update() {
// System.out.println("权限校验");
System.out.println("更新数据");
// System.out.println("日志记录");
}
@Override
public void select() {
// System.out.println("权限校验");
System.out.println("查询数据");
// System.out.println("日志记录");
}
}
package com.shujia.lhw.day27;
public interface UserDao {
public abstract void add();
public abstract void delete();
public abstract void update();
public abstract void select();
}
package com.shujia.lhw.day27;
public class StudentDaoImpl implements StudentDao{
@Override
public void login() {
System.out.println("登录");
}
@Override
public void regist() {
System.out.println("注册");
}
}
package com.shujia.lhw.day27;
public interface StudentDao {
public abstract void login();
public abstract void regist();
}
package com.shujia.lhw.day27;
import java.lang.reflect.Proxy;
/*
动态代理
*/
public class Test {
public static void main(String[] args) {
StudentDaoImpl studentDao = new StudentDaoImpl();
UserDaoImpl userDao = new UserDaoImpl();
// studentDao.login();
// studentDao.regist();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(studentDao);
//static Object newProxyInstance(ClassLoader loader,类<?>[] interfaces,InvocationHandler h)
//返回指定接口的代理类的实例,该接口方法调用分派给指定的调用处理程序
StudentDao sd = (StudentDao)Proxy.newProxyInstance(studentDao.getClass().getClassLoader(), studentDao.getClass().getInterfaces(), myInvocationHandler);
sd.login();
sd.regist();
MyInvocationHandler myInvocationHandler1 = new MyInvocationHandler(userDao);
UserDao userDao1 = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), myInvocationHandler1);
userDao.add();
userDao.delete();
userDao.update();
userDao.select();
}
}
package com.shujia.lhw.day27;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object proxy1;//目标对象,将来你要给谁去代理实现功能,代理对象
public MyInvocationHandler(Object proxy1){
this.proxy1 = proxy1;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("权限校验");
Object obj = method.invoke(proxy1, args);
System.out.println("日志记录");
return obj;
}
}
三、网络编程Test
先启动UploadSercer
package com.shujia.lhw.day27;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class UploadServer {
public static void main(String[] args) throws Exception{
//1、创建服务器端的ServerSocket对象
ServerSocket ss = new ServerSocket(12345);
//2、监听客户端与之的连接,获取对应的Socket对象
Socket s = ss.accept();
//3、获取通道中的字节输入流对象
InputStream inputStream = s.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(isr);
//4、创建普通的字符输入流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("ntFile.txt"));
String line = null;
while((line=br.readLine())!=null){
// if ("over".equals(line)){
// break;
// }
bw.write(line);
bw.newLine();
bw.flush();
}
//服务器给出反馈
//获取通道中字节输出流对象
OutputStream outputStream = s.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
BufferedWriter bw2 = new BufferedWriter(outputStreamWriter);
bw2.write("文件上传成功");
bw2.newLine();
bw2.flush();
//释放资源
bw.close();
s.close();
}
}
后启动UploadClient
package com.shujia.lhw.day27;
import java.io.*;
import java.net.Socket;
/*
按照我们正常的思路加入反馈,结果却没有反应,为什么?
原因是,读取文本可以用null作为一个结束信息,但是呢,在通道内是不能这样结束信息的
所以服务器并不知道客户端已经上传结束了。二客户端还在等着服务器给我反馈,所以就出现了相互等待的现象
如何解决呢?
1、再多谢一条数据,告诉服务器,读到这条数据就说明文件上传完毕,没有数据过来了,让服务器不用继续读了
这样虽然能解决问题,但是呢,不好
2、Socket对象中shutdownOutput方法
*/
public class UploadClient {
public static void main(String[] args) throws Exception{
//1、创建Socket对象
Socket s = new Socket("192.168.17.1",12345);
//2、获取本地的字符输入流对象
BufferedReader br = new BufferedReader(new FileReader("src\\com\\shujia\\lhw\\day25\\DieLockDemo.java"));
//3、获取通道中的字节输出流对象
OutputStream outputStream = s.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
BufferedWriter bw = new BufferedWriter(outputStreamWriter);
String line = null;
while ((line = br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
//自定义一个结束标记
// bw.write("over");
// bw.newLine();
// bw.flush();
//通知服务器我没有数据过来了,你也别等了
s.shutdownOutput();
//获取通道中字节输入流对象
InputStream inputStream = s.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader br2 = new BufferedReader(inputStreamReader);
String s1 = br2.readLine();//阻塞 等待服务给出反馈
System.out.println(s1);
//释放资源
br.close();
s.close();
}
}