天天看点

Day17 JavaSE基础复习 (25)网络编程 (26)反射&JDK新特性(25)网络编程(26)反射&JDK新特性 

(25)网络编程

  1.  ipconfig  //查看本机IP
  2. ping        //测试连接
  3. 每个网络程序都要绑定一个端口号,范围(0-65535)

    编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统占用了

    常用端口:

    mysql:2206          oracle:1521          web:80          tomcat:8080          QQ:4000          feiQ:2425

  4. 网络编程三要素协议:为计算机网络中进行数据交换而建立的规则、标准或约定的集合

    UDP: 面向无连接,数据不安全,速度快;不区分客户端与服务端

    TCP: 面向连接(三次握手),数据安全,速度略低,分为客户端和服务端

             三次握手:客户端先向服务端发起请求,服务端响应请求,传输数据

  5. Socket  套接字

    网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字

    通信的两端都有Socket;网络通信其实就是Socket间的通信;数据在两个Socket间通过IO流传输

    Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port

  6. UDP:

    6.1 发送send

          创建DatagramSocket 随机端口号 

                DatagramSocket socket = new DatagramSocket();

          创建DatagramPacket 指定数据,长度,地址,端口 

                new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);

          使用DatagramSocket发送DatagramPacket

                socket.send(packet);

          关闭DatagramSocket        socket.close();

    6.2 接收receive

          创建DatagramSocket 指定端口号 

                DatagramSocket socket = new DatagramSocket(6666);

          创建DatagramPacket 指定数组,长度

          使用DatagramSocket 接收 DatagramPacket

          关闭DatagramSocket

  7. TCP协议:

    7.1客户端

            Socket socket = new Socket(指定ip,端口);

            InputStream is = new socket.getInputStream();     //获取客户端输入流           优化后:用BufferedReader包装

            OutputStream os = new socket.getOutputStream();     //获取客户端输出流    优化后:用PrintStream包装

            byte[] arr = new byte[1024];

            int len = is.read(arr);                         //读取服务器发来的数据

            syso(new String(arr,0,len));              //将数据转换成字符串打印

            os.write("****".getBytes());                 //客户端向服务器写数据

            socket.close();  //流也会一起关闭

    7.2服务端

            ServerSocket server = new ServerSocket(7.1中的端口);

            Socket socket = sever.accept();         //接受客户端的请求

            InputStream is = new socket.getInputStream();            //获取服务端输入流    优化后:用BufferedReader包装

            OutputStream os = new socket.getOutputStream();     //获取服务端输出流    优化后:用PrintStream包装

            os.write("***".getBytes());                   //服务器向客户端写出数据

            byte[] arr = new byte[1024];

            int len = is.read(arr);                        //读取客户端发过来的数据

            syso(new String(arr,0,len));                //将数据转换成字符串并打印

            socket.close();  //流也会一起关闭

    服务端 可以用while(true){}  循环接收客户端的请求,然后用匿名内部类创建线程,在run方法中,获取输入输出流

(26)反射&JDK新特性 

一.反射

  1.  源文件阶段         *.java文件

    Class clazz = Class.forName("类名");      //作用:读取配置文件

  2. 字节码阶段         *.class文件

    Class clazz = 类名.class                         //作用:当作静态方法的锁对象

  3. 创建对象阶段         new *();

    Class clazz = 引用.getClass();  //该引用指向的就是上边的类 作用:判断是否是同一个字节码对象

  4. Person p = (Person)clazz.newInstance(); //通过无参构造创建对象
  5. Class clazz =Class.forName("完整类名");                  //假设完整类名是com.my.Person        Person类中有name,age属性值

    Constructor c = clazz.getConstructor(String.class,int.class);         //Person类中有一个有参构造(String name,int age)

    Person p = (Person)c.newInstance("李四",24);    //通过有参构造创建对象

    1. Field f = clazz.getField("name");           //获取姓名字段

      f.set(p,"张三");                                       //修改姓名的值

    2. //若Person中的name,age属性被私有,就用暴力反射获取

      Field f = clazz.getDeclaredField("name");  //暴力获取字段

      f.setAccessible(true);                            //去除私有权限

      f.set(p,"张三");                                       //修改姓名的值

  6. Class clazz =Class.forName("完整类名");                  //假设完整类名是com.my.Person        Person类中有eat()方法

    Constructor c = clazz.getConstructor(String.class,int.class); 

    Person p = (Person)c.newInstance("李四",24);    //通过有参构造创建对象

    Method m = clazz.getMethod("eat");                      //获取eat()方法

    m.invoke(p);                 

    Method m2 = clazz.getMethod("eat",int.class)       //获取有参   eat(int num)方法

    m2.invoke(p,2);

  7. 泛型擦除/泛型反射

    ArrayList<Integer> list = new ArrayList<>();             //创建一个只能放整数类型的集合

    Class clazz = Class.forName("java.util.ArrayList");    //获取到字节码对象

    Method m = clazz.getMethod("add");                        //获取到add方法

    m.invoke(list , "abc");                                                //向集合直接添加字符串

二.JDK新特性

  1. JDK5 通过enum实现枚举类

     int ordinal();  //枚举项都是有编号的,返回枚举的编号,从0开始

     int compareTo(E o);  //比较的是编号,返回的是this的编号减去o的编号

     String name();    //获取实例的名称

     <T>T valueOf(Class<T> type,String name)  //通过传字节码对象,名称。 获取枚举项

     values();   //获得所有枚举,可用来遍历,返回值是数组

  2. JDK7

    A:二进制字面量

           syso(0b110);       //输出6

    B:数字字面量可以出现下划线

           syso(100_000);   //输出100000

    C:switch 语句可以用字符串

    D:泛型简化,菱形泛型

    E:异常的多个catch合并,每个异常用或|

    F:try-with-resources  语句,      1.7版标准的异常处理代码

  3. JDK8

    A.接口中可以定义有方法体的方法,static修饰的可以有方法体,如果是非静态的,必须用default修饰

    B.局部内部类访问所在方法中的局部变量必须用final修饰,JDK8之后,可以省略

       必须用final修饰原因:因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的

               当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果

               用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池中的常量还在,也可以继续使用