UDP传输
1:建立udp的socket服务.
2:通过receive方法接收数据
3:将收到的数据存储到数据包对象中
4:通过数据包对象的功能来完成对接收到数据进行解析.
5:可以对资源进行关闭
客户端
/*
按照我们正常的思路加入反馈,结果却没有反应,为什么
原因是,读取文本文件可以用null作为一个结束信息,但是呢,在通道内是不能这样结束信息的
所以服务器并不知道客户端已经上传结束了。而客户端还在等着服务器给我反馈,所以就出现了相互等待的现象。
如何解决呢?
1、再多写一条数据,告诉服务器,读到这条数据就说明文件上传完毕,没有数据过来了,让服务器也不用继续读了
这样做虽然能解决问题,但是呢,不好
2、Socket对象中shutdownOutput方法
*/
public class UploadClient {
public static void main(String[] args) throws Exception {
//1、创建Socket对象
Socket s = new Socket("192.168.7.64", 12345);
//2、获取本地的字符输入流对象
BufferedReader br = new BufferedReader(new FileReader("src\\com\\shujia\\yl\\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();
}
}
服务端
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("netFile.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();
}
}
TCP传输
Socket和ServerSocket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数据的传输
关闭socket
同样,客户端与服务器端是两个独立的应用程序。
类加载器和反射
反射
反射:通过一个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)
//返回与给定字符串名称的类或接口相关联的类对象。 调用此方法相当于:
try {
Class<?> c4 = Class.forName("com.shujia.wyh.day27.Person");
System.out.println(c1==c4);
System.out.println(c2==c4);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
如何通过反射获取Class文件对象中的构造方法并使用呢?
public class ReflexDemo2 {
public static void main(String[] args) throws Exception {
//获取Class文件对象
Class<?> c1 = Class.forName("com.shujia.wyh.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.getDeclaredConstructors();
for(Constructor c: cons2){
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.getDeclaredConstructor(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);
}
}
通过反射获取私有的构造方法并创建对象
public class ReflexDemo3 {
public static void main(String[] args) throws Exception {
//获取类的字节码文件对象
Class<?> c1 = Class.forName("com.shujia.wyh.day27.Person");
//获取私有的构造方法
Constructor<?> con = c1.getDeclaredConstructor(String.class, int.class);
System.out.println(con);
//IllegalAccessException 非法的访问异常
//暴力访问
con.setAccessible(true); //这里的值如果时true的话,表示反射的对象在使用的时候取消Java语言的访问检查
//使用Constructor类中的方法来创建对象
Object o = con.newInstance("明旺", 18);
Person p = (Person) o;
System.out.println(p);
}
}
通过反射获取成员变量并使用
public class ReflexDemo4 {
public static void main(String[] args) throws Exception {
//1、获取字节码文件对象
Class<?> c1 = Class.forName("com.shujia.wyh.day27.Person");
//获取所有的公共成员变量
//public Field[] 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);
}
}
通过反射获取成员方法并使用
public class ReflexDemo5 {
public static void main(String[] args) throws Exception {
//1、获取字节码文件对象
Class<?> c1 = Class.forName("com.shujia.wyh.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("fn4");
fun4.invoke(o);
}
}
反射小练习
通过配置文件运行类中的方法
配置文件:
配置文件里面基本上都是键–值这样的键值存在的
className
com.shujia.wyh.day27.Person
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\\wyh\\day27\\configure.txt");
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");
}
}
我给你ArrayList的一个对象,我想在这个集合中添加一个字符串数据,如何实现呢?
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);
}
}
}
动态代理
代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
举例:春季回家买票让人代买
动态代理:在程序运行过程中产生的这个对象
而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib
Proxy类中的方法创建动态代理类对象
Object invoke(Object proxy,Method method,Object[] args)public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
最终会调用InvocationHandler的方法
InvocationHandler
总复习以及后面的规划
一:初识Java
1、什么是计算机
2、DOS
3、Java
4、JDK,JRE,JVM
5、安装JDK
6、配置环境变量
7、HelloWorld
8、java运行步骤
二、Java基础语法
1、注释
2、关键字
3、标识符
4、常量
5、运算符
+
=
==
||
&&
三目运算符
6、键盘录入
7、语法结构
8、变量
9、方法和数组
三、面向对象
封装
继承
多态
四、常用类
Object
String
StringBuffer、StringBuilder
Arrays
自定义工具类 文档注释
五、集合
Collection
Map
六、IO
异常
File
递归
字节流
字符流
序列化流
七、多线程
三种实现线程方式
解决线程同步安全问题的方案:
1、synchronized关键字
2、lock锁
死锁
等待唤醒机制
线程池(了解几种线程池的区别即可)
八、网络编程
UDP
TCP
九、反射(将上课的案例看懂敲会即可)
今后的学习路线:
Linux
MySql on Linux
Springboot结合mysql实现数据增删改查在页面显示
redis
hadoop
hive(每天练习至少2道hive题)
hbase
...