17.网络编程、反射
package com.atguigu.java2; import java.net.InetAddress; import java.net.UnknownHostException; /* 一、网络编程中两个主要的问题: 1.定位网络上一台或多台主机:定位主机上的特定应用 2.找到主机后,可靠高效地进行数据传输 二、网络编程中两要素 1.提供具体的ip以及端口号 2.提供网络通信协议:TCP/IP参考模型:应用层、传输层、网络层、物理+数据链路层 IP和端口号 在java中使用InetAddress类代表IP IP分类 :Ipv4 和IPv6 域名: www.baidu.com 本地回路地址:127.0.0.1 对应 localhost 端口号标识正在计算机上运行的进程 传输控制协议TCP协议 用户数据报协议UDP */ public class InterAddressTest { public static void main(String[] args) { try { InetAddress inet = InetAddress.getByName("192.168.10.14"); } catch (UnknownHostException e) { e.printStackTrace(); } } }
TCP
package com.atguigu.java2; import org.junit.Test; import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; /* TCP网络编程 练习:客户端发送文件给服务器,服务器端保存到本地, 并返回”发送成功“给客户端,并关闭相应连接 */ public class TCPTest { @Test public void clinet(){ Socket socket = null; OutputStream os = null; FileInputStream fis = null; InputStream is = null; ByteArrayOutputStream baos =null; try { //1. socket = new Socket(InetAddress.getByName("127.0.0.1"), 9988); //2 os = socket.getOutputStream(); // fis = new FileInputStream(new File("timg.jpg")); // byte[] buffer = new byte[1024]; int len; while((len = fis.read(buffer)) != -1) { os.write(buffer,0,len); } //关闭数据的输出 socket.shutdownOutput(); //接受来自服务器端信息,并显示到控制台 is = socket.getInputStream(); baos = new ByteArrayOutputStream(); byte[] buffer1 = new byte[20]; int len1 ; while((len1 = is.read(buffer1))!=-1){ baos.write(buffer1,0,len1); } System.out.println(baos.toString()); } catch (IOException e) { e.printStackTrace(); } finally { //5.关闭流操作 try { baos.close(); } catch (Exception e) { e.printStackTrace(); } try { fis.close(); } catch (IOException e) { e.printStackTrace(); } try { os.close(); } catch (IOException e) { e.printStackTrace(); } try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void server(){ ServerSocket ss = null; Socket socket = null; InputStream is = null; FileOutputStream fos = null; OutputStream os = null; try { //1 ss = new ServerSocket(9988); //2 socket = ss.accept(); //3 is = socket.getInputStream(); //4 fos = new FileOutputStream(new File("longmao.jpg")); byte[] buffer = new byte[1024]; int len; while((len = is.read(buffer))!=-1){ fos.write(buffer,0,len); } os = socket.getOutputStream(); os.write("你好,图片已收到".getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { try { os.close(); } catch (Exception e) { e.printStackTrace(); } try { fos.close(); } catch (IOException e) { e.printStackTrace(); } try { is.close(); } catch (IOException e) { e.printStackTrace(); } try { socket.close(); } catch (IOException e) { e.printStackTrace(); } try { ss.close(); } catch (IOException e) { e.printStackTrace(); } } } }
UDP
package com.atguigu.java2; import org.junit.Test; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; /* UDP的网络编程 */ public class UDPTest { //发送端 @Test public void sender() throws IOException { DatagramSocket socket = new DatagramSocket(); String str= "UDP方式发送信息"; byte[] data = str.getBytes(); InetAddress inet = InetAddress.getLocalHost(); DatagramPacket packet = new DatagramPacket(data,0,data.length,inet,9090); socket.send(packet); socket.close(); } //接受端 @Test public void receiver() throws IOException { DatagramSocket socket = new DatagramSocket(9090); byte[] buffer = new byte[100]; DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length); socket.receive(packet); System.out.println(new String(packet.getData(),0,packet.getLength())); socket.close(); } }
URL
package com.atguigu.java2; import java.net.MalformedURLException; import java.net.URL; /* URL编程 1.URL:统一资源定位符,对应着互联网的某一资源的地址 2.格式: http://localhost:8080/hello.txt?username=sun 协议 主机名 端口号 资源地址 参数列表 */ public class URLTest { public static void main(String[] args) { try { URL url = new URL("https://baike.baidu.com/item/URL%E6%A0%BC%E5%BC%8F/10056474?fr=aladdin"); System.out.println(url.getAuthority()); System.out.println(url.getProtocol()); System.out.println(url.getHost()); //…… } catch (MalformedURLException e) { e.printStackTrace(); } } }
反射
package java3; public class Person { private String name; public int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public Person(String name) { this.name = name; } public void show(){ System.out.println("这是一个人"); } private String showNation(String nation){ return "国籍时"+nation; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
创建运行时类的对象
package java3; /* 反射:动态语言的关键, 动态语言:在运行时代码可以根据某些条件改变自身结构 通过反射创建对应的运行时类的对象 */ import org.junit.Test; public class NewInstanceTest { @Test public void test() throws Exception { Class clazz = Person.class; /*newInstance() : 调用此方法调用运行时类的对象,即person的对象,内部调用空参构造器 在javabean 中要求提供一个public的空参构造器, 1.便于通过反射,创建运行类的对象 2.便于子类继承此运行时类,默认调用super(),保证父类有此构造器 */ Object o = clazz.newInstance(); System.out.println(o);//Person{name='null', age=0} } }
package java3; import org.junit.Test; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectionTest { //反射之前对person类的操作 @Test public void test1() { //1.创建person的构造器 Person p1 = new Person("tom", 12); //2.通过对象调用属性和方法 p1.age = 18; System.out.println(p1.toString()); p1.show(); //person类外部,不可以通过person类的对象调用私有结构,比如:name、showNation } //反射之后 @Test public void test2() throws Exception { //1.通过反射创建person类的对象 Class<Person> clazz = Person.class; Constructor<Person> cons = clazz.getConstructor(String.class, int.class); Person p = cons.newInstance("tom", 12); //2.通过反射,调用person指定的属性 Field age = clazz.getDeclaredField("age"); age.set(p, 10); System.out.println(p.toString());//Person{name='tom', age=10} //3.通过反射,调用person指定的方法 Method show = clazz.getMethod("show"); show.invoke(p);//这是一个人 //通过反射是可以覅用person类的私有结构 Constructor<Person> cons1 = clazz.getDeclaredConstructor(String.class); cons1.setAccessible(true); Person p1 = cons1.newInstance("jerry"); System.out.println(p1.toString());//Person{name='jerry', age=0} Field name = clazz.getDeclaredField("name"); name.setAccessible(true); name.set(p1,"hanmeimei"); System.out.println(p1.toString());//Person{name='hanmeimei', age=0} Method showNation = clazz.getDeclaredMethod("showNation", String.class); showNation.setAccessible(true); String s =(String) showNation.invoke(p1, "中国"); System.out.println(s);//国籍时中国 } /* 关于java.lang.Class类的理解 1.类的加载过程 程序在经过javac.exe命令以后,会生成一个或多个字节码文件。 使用java.exe命令对某个字节码文件进行解析运行。相当于将某个字节码文件加载到内存, 此过程就称为类的加载。加载到内存中的类,称为运行时类,此运行时类,就作为Class的一个实例 2. Class的实例就对应着一个运行时类 3.加载到内存中的运行类,会缓存一定的时间,在此时间之内,可以同过不同的方式类获取Class的实例 */ /* 获取Class的实例的方式(前三种需要掌握),第三种方式频率最高 */ @Test public void test3() throws ClassNotFoundException { //方式一:调用运行时类的属性:.class Class<Person> clazz1 = Person.class; System.out.println(clazz1);//class java3.Person //方式二:通过运行类的对象:调用getClass() Person p1 = new Person(); Class clazz2 = p1.getClass(); System.out.println(clazz2);//class java3.Person //方式三:调用Class的静态方法:forName(String classPath) Class clazz3 = Class.forName("java3.Person"); System.out.println(clazz3); System.out.println(clazz1 == clazz2);//true System.out.println(clazz1 == clazz3);//true //方式四:使用类的加载器ClassLoader ClassLoader classLoader = ReflectionTest.class.getClassLoader(); Class clazz4 = classLoader.loadClass("java3.Person"); System.out.println(clazz1 == clazz4);//true } }
package java4; import java3.Person; import org.junit.Test; import java.lang.reflect.*; /* 获取当前运行时类的属性结构 */ public class OtherTest { @Test public void test(){ Class clazz = Person.class; //了解 //获取属性结构 //getFields():获取当前运行时类及其父类中声明为public的属性 //getMethods() Field[] fields = clazz.getFields(); for(Field f : fields){ System.out.println(f);//public int java3.Person.age } //getDeclaredFields():获取当前运行时类中所有属性,不包含父类中的属性 //getDeclaredMethods(): Field[] declaredFields = clazz.getDeclaredFields(); for(Field f1: declaredFields){ System.out.println(f1);//private java.lang.String java3.Person.name // public int java3.Person.age } } //掌握 @Test public void test2() throws Exception { Class clazz = Person.class; //getConstructors():获取当前运行时类中申明为public的构造器 Constructor[] constructor = clazz.getConstructors(); for(Constructor c :constructor){ System.out.println(c);//public java3.Person(java.lang.String) //public java3.Person(java.lang.String,int) //public java3.Person() } //getDeclaredConstructors():运行时类中所有构造器 Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); for(Constructor c1 :declaredConstructors){ System.out.println(c1); } } @Test public void test3(){ Class clazz = Person.class; //getSuperclass():获取运行时类的父类 //getGenericSuperclass():获取运行时类的带泛型的父类 Class superclass = clazz.getSuperclass(); } //获取运行时类的带泛型的父类的泛型 @Test public void test4(){ Class<Person> clazz = Person.class; Type genericSuperclass = clazz.getGenericSuperclass(); ParameterizedType paramType = (ParameterizedType)genericSuperclass; //获取泛型类型 Type[] actualTypeArguments = paramType.getActualTypeArguments(); for (Type t :actualTypeArguments){ System.out.println(t); } } //掌握:调用指定运行时类的结构:属性、方法、构造器 @Test public void test5() throws Exception { Class clazz = Person.class; //创建运行时类的对象 Person p = (Person)clazz.newInstance(); //获取指定的属性getField 只能获取public的属性不常用,一般用getDeclaredField Field age = clazz.getField("age"); //设置当前属性值 set():参数1:指明设置那个对象的属性,参数二:属性的设值多少 age.set(p,18); //获取当前属性值 get():参数1:指明获取那个对象的属性 int page =(int) age.get(p); System.out.println(page); Field name = clazz.getDeclaredField("name"); //setAccessible(true):保证当前属性是 可访问的 name.setAccessible(true); name.set(p,"tom"); System.out.println(name.get(p));//tom } //掌握 操作指定方法 @Test public void test6() throws Exception { Class clazz = Person.class; Person p = (Person)clazz.newInstance(); /*获取指定的某个方法 * getDeclaredMethod():参数1:指明获取的方法的名称,参数二:获取指定形参列表 *invoke():参数1:方法的调用着,参数二:给方法形参赋值的实参 * invoke()的返回值,即为对应类中调用的方法的返回值 */ Method showNation = clazz.getDeclaredMethod("showNation", String.class); showNation.setAccessible(true); System.out.println(showNation.invoke(p, "CHN")); //国籍时CHN //如何调用静态方法 Method showdesc = clazz.getDeclaredMethod("showdesc"); showdesc.setAccessible(true); showdesc.invoke(Person.class); } }
虽不能至,心向往之