2021-06-06

JavaSE基础(W5.5)总结

Day1

IO流的分类

按流的方向划分:
    1)输入流
    2)输出流
    
按流的类型划分:
    1)字节流
         字节输入流:InputStream(抽象类)
         FileInputStream:针对文件操作的字节输入流(读)
 
         字节缓冲输入流(字节高效输入流):BufferedInpuStream
         字节输出流:OutputStream(抽象类)
         FileOutputStream:针对文件操作的字节输出流(写)
 
 
         字节缓冲输出流(字节高效输出流):BufferedOutputStream
         
 2)字符流:由于字节流操作文本文件的时候(一次读取一个字节的时候,将内容输出在控制台上:可能出现中文乱码)所以才有了字符流!
 
      字符输入流:Reader:读
              字节输入流通向字符输入流的桥梁(转换输入流):InputStreamReader
                    为了书写简单:FileReader
 
 
              字符缓冲输入流(字符高效输入流):BufferedReader
                     特有功能:String readLine() :一次读取一行
 
 
      字符输出流:Writer:写
              字节输出流流通向字符输出流的桥梁(转换输出流):OutputStreamWriter
                     为了书写简单:FileWriter
 
 
              字符缓冲输出流(字符高效输出流):BufferedWriter
                     特有功能:
                            public void newLine():写入一个行的分隔(换行功能)
 字节流:
        字节输出流:OutputStreamStream抽象类
        提供具体的子类:FileOutputStream
        
使用步骤  :
        1)创建一个文件输出流对象
        2)写一些内容(输出到某个盘符下或者当前项目下)
        3)释放资源:流资源(流的底层----->非Java语言实现:本地方法)
        
        
        

字节输出流:写的功能

​
public void write(int b) throws IOException:给当前字节输出流中写入一个字节
public void write(byte[] b) throws IOException:写入一个字节数组
public void write(byte[] b,int off,int len)throws IOException:写一个字节数组的一部分
参数2:从指定位置开始
参数3:指定长度
public class FileOutputStreamDemo {
    public static void main(String[] args) throws IOException {
​
        //具体类创建
        FileOutputStream fos = new FileOutputStream("fos.txt") ; //调用系统资源 执行当前地址:文件fos.txt
        //写
        fos.write("hello,io".getBytes());
        //释放资源:将当前系统资源指向的这个文件将它从内存中释放调用
        fos.close() ;
    }
}
//------------
public class FileOutputStreamDemo2 {
​
    public static void main(String[] args) throws IOException {
        //创建一个输出流对象
        FileOutputStream fos = new FileOutputStream("fos2.txt") ;
​
        //public void write(int b) throws IOException:给当前字节输出流中写入一个字节
​
//        public void write(byte[] b) throws IOException:写入一个字节数组
        byte[] bytes = {97,98,99,101} ;
        fos.write(bytes) ;
​
        fos.write(bytes,0,2);
​
        //释放资源
        fos.close() ;
    }
}
//--------------------------
构造方法
  public FileOutputStream(String name,boolean append) throws FileNotFoundException
  创建一个文件输出流对象,第二个参数为true,就是在文件字节末尾处追加! 
  如何现在将输出一句内容,换一行? 
  windows操作系统:换行符号"\r\n"
public class FileOutputStreamDemo3 {
​
    public static void main(String[] args) throws IOException {
​
        //创建一个文件输出流对象,开启文件末尾字节追加
        FileOutputStream fos = new FileOutputStream("fos3.txt",true) ;
​
        //for循环
        for(int x = 0 ; x < 10 ; x ++){
            fos.write(("hello"+x).getBytes());
            //写入一个换行符号
            fos.write("\r\n".getBytes());
        }
        //关闭资源
        fos.close();
    }
}
​
//-------------------------------
 流中加入异常操作:解决方案---->try...catch...finally 标准格式
 
public class FileOutputStreamDemo4 {
    public static void main(String[] args) {
​
        //method1() ;
​
//        method2() ;
​
        method3() ;
    }
​
    //第三种方式:try...catch...finally
    private static void method3() {
        FileOutputStream fos = null ;
        try {
           fos = new FileOutputStream("fos4.txt") ;
           fos.write("hello,i'm coming...".getBytes());
        } catch (IOException e) {
            e.printStackTrace(); //如果try有问题:代码追踪到源码中,并且有jvm将异常信息以及源码的错误行数都可以 控制台日志体现
        }finally {
            if(fos!=null){
                //释放资源
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
​
    //第二种方式:try...catch...catch
    private static void method2() {
        //创建一个文件输出流对象
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("fos4.txt");
            //写数据
            fos.write("hello,JavaEE".getBytes());
​
            //关闭资源
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
​
    //第一种方式:就是分别try...catch
    private static void method1() {
        //创建一个文件输出流对象
        FileOutputStream fos = null ;
        try {
             fos = new FileOutputStream("fos4.txt") ;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //写数据
        try {
            fos.write("hello,OutputStream".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        //释放资源
        if(fos!=null){
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
​
    }
}
 

 

抽象类:InputStream:表示字节输入流的所有类的超类
  提供的针对文件操作的输入流:FileInputStream
 
使用步骤:
   1)创建文件操作输入流对象
        public InputStream()
 
   2)通过 文件字节输入流对象,读取指定的文件中的内容
   读取数据的功能:
        public int read() throws IOException:一次读取一个字节
        public int read(byte[] b) throws IOException: 读取一个字节数组,返回的是读取的实际字节数
        public int read(byte[] b,int off,int len) throws IOException:读取一部分字节数组
 
   3)释放资源
  一次读取一个字节:
        读取一些文件,中文会出现乱码,原因就是将实际的字节数强制转为char类型,   
        而中文在idea平台:utf-8格式:一个中文对应三个字节,和前面的英文拼接不到一起,就出现中文乱码
​
public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
​
        //创建文件操作输入流对象   
        FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java") ;
     //将获取,判断,赋值直接一次性使用
        //声明一个字节数
        int by = 0 ;
        while((by=fis.read())!=-1){
            System.out.print((char)by);
        }
        //释放资源
        fis.close();
    }
}
public int read(byte[] b) throws IOException: 读取一个字节数组,返回的是读取的实际字节数
字节输入流 一次读取一个字节/一次读取一个字节数组 (第二种方式的读写速率优于第一种方式!)
public class FileInputStreamDemo2 {
​
    public static void main(String[] args) throws IOException {
        byte[] bufferBytes = new byte[1024] ;
        //实际字节数
        int len = 0 ;
        //赋值,判断,获取
        while((len=fis.read(bufferBytes))!=-1){
            //获取内容 :一定带上 0,实际字节数
            System.out.println(new String(bufferBytes,0,len));
        }
        //释放资源
        fis.close();
    }
}

复制文件

使用文件字节输入流:FileInputStream :一次读取一个字节/一次读取一个字节数组
     当前输入流对象指向:FileOutputStreamDemo.java
 
目标文件--->需要复制的盘符地址
      使用文件字节输出流:FileOutputStream: 写一个字节/写一个字节数组,从0开始,写入实际长度
public class CopyFileDemo {
    public static void main(String[] args) throws Exception {
        //创建一个文件字节输入流对象
        FileInputStream fis = new FileInputStream("FileOutputStreamDemo.java") ;
        //创建一个文件字节输出流对象
        FileOutputStream fos  = new FileOutputStream("D:\\要复制到某个盘符") ;
​
        long start = System.currentTimeMillis() ;
​
        //读写复制操作
        //方式1:一次读取一个字节
    //   int by = 0 ;
       // while((by=fis.read())!=-1){
            //读一个字节,写入一个字节
         //   fos.write(by);
      //  }
​
//方式2:一次读取一个字节数组
        byte[] bytes = new byte[1024] ;
        int len = 0 ;
        while((len=fis.read(bytes))!=-1){
            //写入一个字节数组,并且从0开始,写入实际的字节数
            fos.write(bytes,0,len);
        }
​
        long end = System.currentTimeMillis() ;
        System.out.println("共耗时:"+(end-start)+"毫秒");
        //关闭资源
        fos.close();
        fis.close();
    }
}

复制图片

将当前项目目录下的图片复制到某个盘符下
public class CopyImage {
    private static FileOutputStream fos = null ;
    private static FileInputStream fis = null ;
​
    public static void main(String[] args) throws Exception {
​
        long start = System.currentTimeMillis() ;
       // copy("图片.jpg","D:\\需要复制的盘符地址\\图片.jpg") ;
        copy2("图片   .jpg","D:\\需要复制的盘符地址\\图片.jpg") ;
​
        close(fos,fis) ;
​
        long end = System.currentTimeMillis() ;
​
        System.out.println("共耗时"+(end-start)+"毫秒");
    }
​
    //一次读取一个字节数组
    private static void copy2(String srcFile, String destFile) throws  Exception {
        //封装源文件--字节输入流对象
​
        fis = new FileInputStream(srcFile) ;
        //封装目的地文件
        fos = new FileOutputStream(destFile) ;
​
        //读写操作
        byte[] bytes = new byte[1024] ;
        int len = 0 ;
        while((len=fis.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }
        close(fos,fis);
    }
    //一次读取一个字节
    private static void copy(String srcFile, String destFile) throws  Exception {
        //封装源文件--字节输入流对象
        fis = new FileInputStream(srcFile) ;
        //封装目的地文件
        fos = new FileOutputStream(destFile) ;
        //读写操作
        int by = 0 ;
        while((by=fis.read())!=-1){
            fos.write(by);
        }
        close(fos,fis);
    }
    //流资源关闭的功能
    private static void close(FileOutputStream fos,FileInputStream fis)  {
        if(fos!=null){
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if(fis!=null){
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
​
}
​

缓冲流复制

Java提供了比一次读取一个字节数组更高效的方式:缓冲流
BufferedOutputStream
   BufferedOutputStream(OutputStream out) :指定默认的缓冲长度:足够大了
      写
        public void write(int b)
        public void write(byte[] b,int off,int len)
BufferedInputStream
   BufferedInputStream(InputStream in)
      读
      public int read()
      public int read(byte[] bytes)    
      public int read(byte[] bytes,int offset,int len)
 
 
内部只是提供一个字节数组(缓冲区):长度8192个长度
构造方法都是默认的缓冲区大小,文件的操作还需要通过最底层的基本的字节流操作
缓冲流都是不直接操作文件,仅仅是提供内部缓冲区(提高读写效率!)
public class BufferedStreamDemo {
    public static void main(String[] args) throws Exception{
​
//创建一个字节缓冲输入流对象:
    BufferedInputStream bis = new BufferedInputStream(
                new FileInputStream("FileOutputStreamDemo.java")) ;
                
                //一次读取一个字节数组
        byte[] bytes = new byte[1024] ;
        int len = 0 ;
        while((len=bis.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
        //关闭
        bis.close();
    }
}

视频文件复制

将D盘下的冒泡.mp4视频文件复制到当前项目下的copy.mp4
​
   使用基本的字节流一次读取一个字节数组  
   耗时247毫秒
   使用字节缓冲流一次读取一个字节数组
   耗时78毫秒
 
针对一个文件读写复制几种方式?
    基本的字节流:一次一个字节
    基本的字节流:一次一个字节数组
 
    字节缓冲流:一次一个字节
    字节缓冲流:一次一个字节数组
public class CopyMp4 {
    public static void main(String[] args)  throws  Exception{
        long start = System.currentTimeMillis() ;
       // copyMp4("D:\\冒泡.mp4","copy.mp4") ;
        copyMp4_2("D:\\冒泡.mp4","copy.mp4") ;
​
        long end = System.currentTimeMillis() ;
        System.out.println("耗时"+(end-start)+"毫秒");
    }
​
    //高效流:字节缓冲输入流一次读取一个字节数组
    private static void copyMp4_2(String src, String dest) throws Exception {
​
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src)) ;
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest)) ;
​
        //一次读取一个字节数组
        byte[] bytes = new byte[1024] ;
        int len = 0 ;
        while((len=bis.read(bytes))!=-1){
            bos.write(bytes,0,len);
        }
​
        //释放
        bos.close();
        bis.close();
    }
​
    //基本的字节流读写复制(一次读取一个字节数组)
    private static void copyMp4(String src, String dest) throws Exception {
​
        FileInputStream fis = new FileInputStream(src) ;
        FileOutputStream fos = new FileOutputStream(dest) ;
​
        //一次读取一个字节数组
        byte[] bytes = new byte[1024] ;
        int len = 0 ;
        while((len=fis.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }
​
        //释放
        fos.close();
        fis.close();
    }
}

字符流

字符流
      字符输入
      字符输出
Writer(抽象类)
        子类:字符转换输出流:OutputStreamWriter 是字符流通向字节流的桥梁
​
构造方法:
    OutputStreamWriter(OutputStream out) :创建转换输出流对象:平台默认编码集(utf-8)
    OutputStreamWriter(OutputStream out,String charsetName):使用指定的字符集编码
public class OutputStreamWriterDemo {
    public static void main(String[] args) throws Exception{
​
        //创建一个字符输出流对象
      //  OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"),"utf-8") ;
        OutputStreamWriter osw = new OutputStreamWriter(
           new FileOutputStream("osw.txt")) ;
                
            osw.write("hello,字符流");
            //关闭流的之前,刷新该流(将字符流的内存中底层保存的字节刷新)
            osw.flush();
​
            //关闭资源 --- 关闭系统资源指向文件的 线程!
             osw.close(); //内存对象已经为null(流已经关闭)
字符输入
Reader(抽象类)
    InputStreamReader 是字节流通向字符流的桥梁
    构造方法:
    public InputStreamReader(InputStream in):使用默认字符集进行解码(utf-8:跟idea的配置有关系)
    public InputStreamReader(InputStream in,String charsetName):使用指定的字符集进行解码
 
   在读写的时候,必须要保证编码和解码统一!
public class InputStreamReaderDemo {
​
    public static void main(String[] args) throws  Exception{
    
    //创建字符输入流对象:使用字符转换输入流
    InputStreamReader isr =
                new InputStreamReader(new FileInputStream("osw.txt"));
                
                //一次读取一个字符数组
        char[] chs = new char[1024] ;
        int len = 0 ;
        while((len=isr.read(chs))!=-1){
            System.out.println(new String(chs,0,len));
        }
​
        //释放
        isr.close();
    }
}

字符流复制文件

针对图片文件,视频文件,音频文件等等----都是直接使用字节流!
 
字符转换流的便捷类:只是为了书写简单
       InputStreamReader---->FileReader(File file)/FileReader(String pathname) :平台默认的解码集(idea---utf-8)
       OutputStreamWriter --->FileWriter(File file)/FileWriter(String pathname):默认的编码
public class CopyFile {
​
    public static void main(String[] args) throws  Exception{
    
    //针对文件操作的字符输入流
        FileReader fr = new FileReader("CopyMp4.java") ;
        //针对文件操作的字符输出流
        FileWriter fw = new FileWriter("D:\\JavaEE_2104\\EE_day25\\code\\a.java");
​
        //一次读取一个字符数组
        char[] chs = new char[1024] ;
        int len = 0 ;
        while((len=fr.read(chs))!=-1){
            //写
            fw.write(chs,0,len);
            //刷新
            fw.flush() ;
        }
​
        //关闭
        fw.close();
        fr.close();
    }
}
字符缓冲输入流和字符缓冲输出流:提供默认的缓冲区大小,读写的操作还需要交给底层字节流
  为了针对文本文件操作,提高执行效率!
  BufferedWriter
       将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
  构造方法
   BufferedWriter(Writer out)
      成员方法:
    public void newLine():换行功能
 
  字符缓冲输入流:BufferedReader
  构造方法:
       public BufferedReader(Reader in)
 
       特有功能:
           public String readLine()
 
public class BufferedStreamDemo {
    public static void main(String[] args)throws  Exception {
   
     BufferedReader br = new BufferedReader(new FileReader("bw.txt")) ;
    String line = null ;
        while((line=br.readLine())!=null){
            System.out.println(line);
        }
        //释放资源
        br.close();
        
        //读写复制操作:
        //将当前项目下的OutputStreamWriterDemo.java复制D:\JavaEE_2104\EE_day25\code\\day25.java
       //字符缓冲输入流
        BufferedReader br2 = new BufferedReader(
                new FileReader("OutputStreamWriterDemo.java")) ;
        //字符缓冲输出流
        BufferedWriter bw2 = new BufferedWriter(
                new FileWriter("D:\\JavaEE_2104\\EE_day25\\code\\day25.java"))  ;
        String line2 = null ;
        while((line2=br2.readLine())!=null){
            bw2.write(line2);
            bw2.newLine();
            bw2.flush();
        }
        //关闭资源
        bw2.close();
        br2.close();
    }
}

键盘录入三种

键盘录入三种
   1)main方法的参数(早期的)
   2)jdk5以后提供的Scanner
   3)BufferedReader(Reader r)
Properties 继承自Hashtable<K,V>---->实现Map<K,V>接口
       表示了一个持久的属性集
 
 Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
 
  构造方法
  public Properties()Properties 继承自Hashtable<K,V>---->实现Map<K,V>接口
       表示了一个持久的属性集
 
 Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
 
  构造方法
  public Properties()public class Test {
    public static void main(String[] args) throws Exception{
​
        //创建一个字符缓冲输入流对象
       // Scanner sc = new Scanner(System.in) ;
​
        InputStream in = System.in ;
        //抽象类指向子类
        Reader r = new InputStreamReader(in) ;
​
        BufferedReader br = new BufferedReader(r) ;
​
        //提示
        System.out.println("请您输入一个int类型的内容:");
        String line = br.readLine(); //阻塞式方法: 不录入内容,一直等待
​
        int i = Integer.parseInt(line); //line:数字字符串
        System.out.println("您输入的数据是:"+i);
    }
}
​

Day2

Properties

Properties 继承自Hashtable<K,V>---->实现Map<K,V>接口
       表示了一个持久的属性集
 
 Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
 
 构造方法
 public Properties()
public class PropertiesDemo {
​
    public static void main(String[] args) {
​
        //Properties没有泛型,属于Map的一个子实现类
        //使用Map接口的功能操作
​
        //创建一个属性列表
        Properties properties = new Properties() ;
​
        //put
        properties.put("张三",30) ;
        properties.put("李四",40) ;
        properties.put("王五",50) ;
        properties.put("赵六",25) ;
​
        //遍历:Map集合遍历方式: 推荐:keySet()
        Set<Object> keySet = properties.keySet();
        for(Object obj :keySet){
            //通过键获取值
            Object value = properties.get(obj);
            System.out.println(obj+"---"+value);
        }
    }
}

关于属性集合类的特有功能:

​
   添加方法
       public Object setProperty(String key,String value)
 
   遍历:
           public Set<String> stringPropertyNames()
    通过键获取值
           public String getProperty(String key)
public class PropertiesDemo2 {
​
    public static void main(String[] args) {
        //创建一个属性集合类
        Properties prop = new Properties() ;
​
        //添加
        prop.setProperty("1","文章") ;
        prop.setProperty("2","高圆圆") ;
        prop.setProperty("3","马伊琍") ;
        prop.setProperty("4","赵又廷") ;
        prop.setProperty("4","王宝强") ;
​
        //遍历
        Set<String> keySet = prop.stringPropertyNames();
        for(String key:keySet){
            //通过键获取值
            String value = prop.getProperty(key);
            System.out.println(key+"---"+value);
        }
    }
}

关于属性集合类的应用;

  1)因为键和值都是String,所以可能将键和值的保存在文本文件或者配置文件中 :加载过程
           public void load(Reader reader)throws IOException
           public void load(InputStream in)throws IOException
 
   2)将属性集合类中的内容写出到某个文件中:保存过程
       public void store(OutputStream out,String comments) throws IOException
                   参数1:当前字节输出流
                   参数2:给当前属性列表中写入完毕之后,注释的内容
    public void store(Writer writer,String comments) throws IOException
   将当前项目下的name.txt内容加载到属性集合类中
public class PropertiesDemo3 {
    public static void main(String[] args) throws IOException {
​
      //  myLoad() ;
     //   mySotre() ;
    }
​
    //保存:将当前属性集合类中的内容,输出在某个文件中
    private static void mySotre() throws IOException {
        //创建一个属性列表
        Properties prop = new Properties() ;
        prop.setProperty("马伊琍","35") ;
        prop.setProperty("文章","26") ;
        prop.setProperty("姚笛","22") ;
        prop.setProperty("王宝强","35") ;
        prop.setProperty("马蓉","30") ;
​
        //保存
        prop.store(new FileWriter("userList.txt"),"name's list");
    }
​
    //加载:将name.txt内容加载到属性集合类中
    private static void myLoad() throws IOException {
        //创建一个属性集合类
        Properties prop = new Properties() ;
        System.out.println(prop);
        //加载
        //字符流
        Reader r = new FileReader("name.txt") ;
        prop.load(r);
​
        //遍历
        Set<String> keySet = prop.stringPropertyNames();
        for (String key: keySet) {
            String value = prop.getProperty(key) ;
            System.out.println(key+"---"+value);
        }
        //System.out.println(prop);
    }
}

 

如果我们的配置文件后缀名xx.properties
  操作步骤:
         src目录下---->类路径
         将properties配置文件放置在src目录下
public class PropertiesDemo4 {
​
    public static void main(String[] args) throws IOException {
​
InputStream inputStream = PropertiesDemo4.class.getClassLoader().getResourceAsStream("user.properties");
        //创建属性集合类中
        Properties prop = new Properties() ;
        prop.load(inputStream);
​
        //System.out.println(prop);
        Set<String> keySet = prop.stringPropertyNames();
        for(String key:keySet){
​
            System.out.println(key+"---"+prop.getProperty(key));
        }
    }
}

获取本机ip字符串形式及主机名称UDP实现

一个具体类中,没有字段,没有构造方法,
那么这个类只有成员方法,成员方法里面存在静态功能,返回值是它本身!
​
单例模式:
    Runtime
    private static Runtime currentRuntime = new Runtime() ;
    private Runtime(){}
    public static Runtime getRuntime(){
        return currentRuntime
}
​
public static InetAddress getByName(String host):给定主机名称,可以获取互联网ip地址对象!
参数:可以传递主机名称/ip地址名称
​
public String getHostAddress():获取ip地址字符串形式
public String getHostName():获取主机名称
public class InetAddressDemo {
    public static void main(String[] args) throws UnknownHostException {
​
        InetAddress inetAddress = InetAddress.getByName("本机ip地址");
​
        //获取ip地址字符串文本
        String ip = inetAddress.getHostAddress();
        System.out.println(ip);
​
        //获取主机名称
        String hostName = inetAddress.getHostName();
        System.out.println(hostName);//本机名称  
    }
}
​
UDP协议发送端的实现步骤: (不需要建立连接通道,以"数据报包"的方式发送数据)
   DatagramSocket表示用来发送和接收"数据报包"的套接字
  1)创建发送端的Socket:  DatagramSocket
          public DatagramSocket() throws SocketException{}
   2) 创建 "数据报包"对象
           public DatagramPacket(byte[] buf,int length,InetAddress address,int port)
   3)发送数据报包
           public void send(DatagramPacket p) throws IOException
 
   4)释放资源
           close()关闭socket对象
public class SendDemo {
    public static void main(String[] args) throws IOException {
        //创建发送端的Socket:  DatagramSocket
        DatagramSocket ds = new DatagramSocket() ;
​
        String messageStr = "输出字符" ;
        byte[] bytes = messageStr.getBytes();
        int length = bytes.length ;
        InetAddress inetAddress = InetAddress.getByName("10" +
                ".12.152.129");
        int port = 10086 ;
        DatagramPacket dp = new DatagramPacket(bytes, length, inetAddress, port);
​
        //3)发送数据
        ds.send(dp);
        System.out.println("当前数据已经发送...");
​
        //4)释放资源
        ds.close();
    }
}

UDP协议接收端实现

UDP协议接收端实现
 
  1)创建接收端的Socket
       public DatagramSocket(int port) throws SocketException:绑定端口号
 
  2)数据一个数据报包对象:DatagramPacket
       接收容器
       public DatagramPacket(byte[] buf, int length) :获取的是缓冲区的数据(不是真实数据)
          一般情况:byte[] bytes = new byte[1024] ; 自定义字节缓冲区
 
 3)接收
     public void receive(DatagramPacket p):阻塞式方法:在接收数据之前,一直处于阻塞状态,直到
      当前接收端监听客户端口号了
 4) 获取缓冲区的传递的真实数据
       public byte[] getData():获取真实的字节数组
       public int getLength():获取实际长度
       将获取的字节数据---->String(byte[] bytes,int offset,int length)
       获取哪个发送端传递的数据:ip 文本形式:
               public InetAddress getAddress()
                           IntegerAddss--->public String getHostAddress()
 
 5)使用完毕,关闭接收端
 
 接收端不能运行多次,否则出现异常了,端口号被占用!
public class ReceiveDemo {
    public static void main(String[] args) throws IOException {
​
        System.out.println("接收端等待发送数据...");
​
        //创建接收端的Socket
        DatagramSocket ds = new DatagramSocket(10086) ;
​
        // 接收容器:数据报包
        //定义一个字节缓冲区
        byte[] bytes = new byte[1024] ;
        int length = bytes.length ;
        DatagramPacket dp = new DatagramPacket(bytes,length) ;
​
        //接收
        ds.receive(dp);
        System.out.println("已经获取发送数据准备解析...");
​
        byte[] bytes2 = dp.getData();
        int len = dp.getLength();
        //获取ip地址
        String ip = dp.getAddress().getHostAddress();
        String receiveMsgStr = new String(bytes2,0,len) ;
        System.out.println("data from " + ip +"and content is:  "+receiveMsgStr);
        //关闭资源
        ds.close();
    }
}

键盘录入,让接收端接收信息

udp发送端不断的键盘录入数据,当前录入是 "over/886",结束,接收端不断的接收数据!
键盘录入数据采用的是:BufferedReader的readLine()功能来操作

发送

public class SendDemo {
    public static void main(String[] args) {
        //创建一个字符缓冲输入流
​
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;
        //创建一个送端的Socket对象
        DatagramSocket ds = null ;
​
        try {
             ds = new DatagramSocket() ;
            String line = null ;
            while((line=br.readLine())!=null){
                //自定义结束条件
                if("886".equals(line)){
                    break ;
                }
                //创建数据报包
                DatagramPacket dp = new DatagramPacket(
                        line.getBytes(),
                        line.getBytes().length,
                        InetAddress.getByName("10.12.152.129"),
                        10010);
                ds.send(dp);
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(ds!=null){
                ds.close();
            }
        }
    }
}
​

接收

Udp接收端不断的接收数据,接收端一般不关闭(模拟真实场景)
​
public class ReceiveDemo {
    public static void main(String[] args)  throws  Exception{
        try {
            System.out.println("等待接收");
            DatagramSocket ds =new DatagramSocket(10010) ;
​
​
        while(true){
            //创建接收端的Socket对象
                //创建数据报包:接收容器
       DatagramPacket dp = new DatagramPacket(new byte[1024],new byte[1024].length) ;
                //接收
                ds.receive(dp);
​
                //准备解析真实数据
                String str = new String(dp.getData(),0,dp.getLength()) ;
                String ip = dp.getAddress().getHostAddress() ;
                System.out.println("data from: "+ip+" and content is: "+str );
//                ds.close(); //接收端不需要关闭
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用UDP在一个窗口下聊天

需要两条线程:发送端发消息的线程
      接收端接收消息的线程
 
创建线程的方式:(除过线程池)
       1)继承自Thread类
       2)实现Runnable接口 ---> 能够多个线程占用的 内存空间(共享共用)
           代理----静态代理模式
public class ChatRoom {
    public static void main(String[] args) throws Exception{
​
        //创建两端的Socket对象
        //发送端:
        DatagramSocket ds = new DatagramSocket() ;
        //接收端
        DatagramSocket ds2 = new DatagramSocket(12306) ;
​
        //创建资源类对象
        //发送端的资源类以及接收端端的子类
        SendThread st  = new SendThread(ds) ;
        ReceiveThread rt = new ReceiveThread(ds2) ;
​
        //创建线程对象
        Thread t1 = new Thread(st) ;
        Thread t2 = new Thread(rt) ;
        t1.start();
        t2.start();
    }
}
//-----------------
//发送资源类
public class SendThread implements  Runnable {
​
    private DatagramSocket ds ;
    public SendThread(DatagramSocket ds){
        this.ds = ds ;
    }
​
    @Override
    public void run() {
        try {
            //不断键盘录入数据
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in)) ;
            String line = null ;
            while((line=br.readLine())!=null){
                if("over".equals(line)){
                    break ;
                }
​
                //创建数据报包
                DatagramPacket dp = new DatagramPacket(line.getBytes(),
                        line.getBytes().length,
                        InetAddress.getByName("ip地址"),
                        12306);
​
                //发送数据
                ds.send(dp) ;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(ds!=null){
                ds.close();
            }
        }
​
    }
}
//---------------------
//接收端
public class ReceiveThread implements Runnable {
​
    private DatagramSocket ds ;
    public ReceiveThread(DatagramSocket ds){
        this.ds = ds ;
    }
    @Override
    public void run() {
        try {
            while(true){
                //创建接收端的Socket对象
                //创建数据报包:接收容器
                DatagramPacket dp = new DatagramPacket(new byte[1024],new byte[1024].length) ;
                //接收
                ds.receive(dp);
​
                //准备解析真实数据
                String str = new String(dp.getData(),0,dp.getLength()) ;
                String ip = dp.getAddress().getHostAddress() ;
                System.out.println("data from: "+ip+" and content is: "+str );
​
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //接收不需要关闭
    }
}

使用TCP/IP方式发送数据

 TCP/IP协议:客户端发送的过程
 
   1)创建客户端的Socket
           public Socket(String host,int port) throws UnknownHostException,IOException
   2)public OutputStream getOutputStream()throws IOException
           获取当前客户端对象所在的通道内的输出流对象
   3)使用当前通道内的字节输出流 写数据过去
   4)释放资源
public class ClientDemo {
    public static void main(String[] args) throws IOException {
​
        //1)创建客户端的Socket
        Socket socket = new Socket("10.12.152.129",6666) ;
​
        //2)获取当前客户端对象所在的通道内的输出流对象
        OutputStream outputStream = socket.getOutputStream();
​
        //3)写数据
        outputStream.write("hello,TCP,我来了".getBytes());
​
        //4)释放资源
        socket.close();
    }
}
服务器端
   1)创建服务器端的Socket  :此类实现服务器套接字
       public ServerSocket(int port)
               throws IOException
   2)监听客户端连接
       public Socket accept()
                throws IOException
 
  3)     通过监听到的客户端对象 获取通道的输入流
       public InputStream getInputStream()
​
  4)关闭资源
       服务器端关闭
public class ServerSocketDemo {
    public static void main(String[] args) throws IOException {
​
        //创建服务器端的Socket
        ServerSocket ss = new ServerSocket(6666) ; //一旦能成功,就立即建立通道
        System.out.println("服务器正在等待连接...");
​
        //2)监听并获取客户端的socket对象
        Socket socket = ss.accept(); //阻塞式方法 如果没有监听到,一直等
        //3)获取通道内的输入流
        InputStream inputStream = socket.getInputStream();
        //一次读取一个字节数组
        byte[] bytes = new byte[1024] ;
        int len = inputStream.read(bytes);
        String str = new String(bytes,0,len) ;
​
        //通过监听到客户端的socket对象获取ip地址
        String ip = socket.getInetAddress().getHostAddress();
        System.out.println("data from :" +ip +" content is :"+str);
        System.out.println("服务器端接收完毕...");
        
        //释放资源
        ss.close();
​
    }
}
​

Day2.5

什么是反射

什么是反射?
   反射就是获取一个类的字节码文件,然后加载该类的所有的成员
   成员变量所在类---->Field
   成员方法所在类---->Method
   构造方法所在类--->Constructor
   给成员变量赋值通过Field,调用成员方法Method,通过构造器创建的对象...
 //获取一个类的字节码文件对象
//1)Object类的getClass()
        Person p = new Person() ;
        Class c1 = p.getClass();
        System.out.println(c1);
         System.out.println(c1.getName());//获取当前Person类的全限定名称com.qf.reflect_01.Person
         
//----------------------
//2)任意Java类型的class属性
        Class c2 = Person.class ;
        System.out.println(c2);
        System.out.println(c2.getName());
        System.out.println(c1==c2);
//----------------
//3)Class的静态功能
        Class c3 = Class.forName("com.qf.reflect_01.Person") ;
        System.out.println(c3);//class com.qf.reflect_01.Person

通过反射获取一个类的构造器并且创建当前类对象

public class Reflect_getCon {
    public static void main(String[] args) throws Exception {
    
    Class clazz = Class.forName("com.qf.reflect_01.Person") ;
    
    Constructor con = clazz.getConstructor() ;
    
    Object obj = con.newInstance();
        System.out.println(obj);
        
     //之前写法
        Person p = new Person() ;
        System.out.println(p);
通过反射获取指定的构造方法(非公共),并创建该类实例
私有的构造方法不能直接new的
​
public class Reflect_getCon2 {
​
    public static void main(String[] args) throws Exception {
​
        //获取Person类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person");
        
        Constructor con = clazz.getDeclaredConstructor(String.class,int.class) ;
        con.setAccessible(true);
访问Person类的默认修饰符的构造方法,并且创建当前类实例
​
public class Refelect_getCon3 {
​
    public static void main(String[] args) throws Exception {
​
​
        //获取当期类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person") ;
        //获取构造器Constructor
        Constructor con =  clazz.getDeclaredConstructor(String.class,int.class,String.class) ;
​
       //构造方法:默认修饰符
        //取消Java语言访问检查
        con.setAccessible(true);
​
        //创建该类实例
        Object obj = con.newInstance("高圆圆",41,"鄠邑区") ;
        System.out.println(obj);
​
    }
}

通过反射方式获取成员变量Field,并给其进行赋值!

//之前的写法:
       //通过无参构造方法创建UI小
        //Person person = new Person() ;
        //person.setName("高圆圆") ;
        //person.setAge(41) ;
public class ReflectDemo {
​
    public static void main(String[] args) throws  Exception{
        //1)获取指定的类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person") ;
        
        //方式1:通过无参构造器创建实例
        //2)通过反射获取单个公共的构造方法,无参
       /* Constructor constructor = clazz.getConstructor();
        //System.out.println(constructor);
        //3)通过构造器创建当前类实例
        Object obj = constructor.newInstance();
        System.out.println(obj);*/
        
        
        //方式1:通过无参构造器创建实例
        //2)通过反射获取单个公共的构造方法,无参
       /* Constructor constructor = clazz.getConstructor();
        //System.out.println(constructor);
        //3)通过构造器创建当前类实例
        Object obj = constructor.newInstance();
        System.out.println(obj);*/
        
         //方式2:直接创建当前类实例
       //Class类的功能:直接通过当前类的字节码文件对象创建当前类对象
        //public T newInstance()
        Object obj = clazz.newInstance();
        System.out.println(obj);
        
        //获取指定的单个的字段(成员变量):公共字段
        //name:公共的字段
        //public Field getField(String name):参数名称为"成员变量名称"
        Field nameField = clazz.getField("name");
        
        //给当前Field所代表的的指定的字段name来进行赋值
//        public void set(Object obj,Object value)
        //将指定的值绑定在当前类的实例上
        nameField.set(obj,"张三");
        
        System.out.println(obj);
        
        
        //获取age所在的Field对象,为其赋值
        //Field getDeclaredField(String name):获取指定的字段Field
        Field ageField = clazz.getDeclaredField("age");
​
        //取消Java语言访问检查
        //私有属性
        ageField.setAccessible(true);
        //赋值
        ageField.set(obj,41);
        System.out.println(obj);
​
        System.out.println("----------------------------");
        Field addressField = clazz.getDeclaredField("address");
        addressField.setAccessible(true);
        addressField.set(obj,"山西省");
        System.out.println(obj);
    }
}

反射面试题

现在有一个ArrayList<String>,如何实现给里面存储Integer类型呢?
​
可以,通过反射方式操作:-----获取Class---->Method--->invoke(当前类实例,方法实际参数)
​
​
public class Test {
​
    public static void main(String[] args) throws Exception {
​
        //创建一个ArrayList<String>
        ArrayList<String> array = new ArrayList<String>() ;
        array.add("hello") ;
        array.add("world") ;
        array.add("javaee") ;
        System.out.println(array);
        System.out.println("--------------------");
       // array.add(100) ;
​
        //通过反射方式调用add方法
        //Object的getClass()获取字节码文件对象
        Class clazz = array.getClass() ;
        //clazz创建当前类实例
        Object obj = clazz.newInstance();//通过反射创建
​
        //获取Method对象:方法名 add
        Method addMethod = clazz.getMethod("add", Object.class);
        //调用方法
        addMethod.invoke(obj,"mysql") ;
        addMethod.invoke(obj,100) ;
        addMethod.invoke(obj,50) ;
​
        System.out.println(obj);
    }
}
​
​

通过反射方式来调用Person类中的成员方法(非静态的)

public class ReflectDemo {
​
    public static void main(String[] args) throws Exception{
​
        //获取Person类的字节码文件对象
        Class clazz = Class.forName("com.qf.reflect_01.Person");
        
         //无参构造方法创建对象:       
        Constructor con = clazz.getConstructor();
        //创建Person类的实例
        Object obj = con.newInstance();
        
         Method showMethod = clazz.getMethod("show");
         
           Object returnObj = showMethod.invoke(obj);
        System.out.println(returnObj);
        
        
        //获取指定的Method
        Method functionMethod = clazz.getDeclaredMethod("function", int.class);
        //取消Java语言访问检查
        functionMethod.setAccessible(true);
​
        Object retunrObj2 = functionMethod.invoke(obj, 27);
        System.out.println(retunrObj2);
        
        Method methodM = clazz.getDeclaredMethod("method") ;
        methodM.setAccessible(true );
        Object returnObj3 = methodM.invoke(obj);
    }
}
反射的应用2: Class.forName("全限定名称"):参数为字符串:被经常用在配置文件中
​
public class Test2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException,
            IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
​
        //创建一个学生类
        Student s = new Student() ;
        s.love();
        //代码不断变化
        //工人类
        Worker worker = new Worker() ;
        worker.love();
        
        System.out.println("-----------------------------------");
        
        InputStream inputStream = Test2.class.getClassLoader().
                getResourceAsStream("class.properties");
         
         //创建属性集合列表
        Properties prop = new Properties() ;
        prop.load(inputStream);
        System.out.println(prop);
        
        //通过key获取value
        String className = prop.getProperty("className");
        String methodName = prop.getProperty("methodName");
        
        //反射获取当前className里面的类的字节码文件对象
        Class clazz = Class.forName(className) ;
       // System.out.println(clazz);
        //直接当前类实例
        Object obj = clazz.newInstance();
​
        //反射获取Method对象
        Method method = clazz.getMethod(methodName);
        method.invoke(obj) ;
    }
}
//------------
public class Student {
​
    public void love(){
        System.out.println("爱学习,爱Java");
    }
}
//------------------
public class Worker {
    public void love(){
        System.out.println("爱生活,爱敲代码...");
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值