`

深入反射、IO文件、字节流

    博客分类:
  • j2se
 
阅读更多

第一:反射相关的概念

1.反射中调用构造函数默认都是调用无参构造函数,因为我们在写java类的时候都要写上无参构造
newInstance声明新实例
3.getDeclaredFields表示全部的属性都能获得。getFields是表示只能获取公共的属性
3.给p3的name属性赋值,属性根据属性名来区分
4.Accessible可以访问,用于访问私有属性
方法:
5.方法通过方法名和参数列表共同决定
6.invoke是调用

 

第二:反射相关的代码

package test;

public class Pet{
 public String name;
 private int age;
 private String color;
 

 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;
 }
 public String getColor() {
  return color;
 }
 public void setColor(String color) {
  this.color = color;
 }
 
 public Pet() {
  super();
  // TODO Auto-generated constructor stub
 }
 public Pet(String name, int age, String color) {
  super();
  this.name = name;
  this.age = age;
  this.color = color;
 }
 @Override
 public String toString() {
  return "Pet [name=" + name + ", age=" + age + ", color=" + color + "]";
 }
 public void eat(){
  System.out.println(name+"正在吃。。。。");
 }
 public void eat(String food){
  System.out.println(name+"正在吃"+food);
 }

}

 

 

package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ClassTest {
 public static void main(String[] args) {
  try {
   //1。获取Class对象
   Class<Pet> cls = (Class<Pet>) Class.forName("test.Pet");
   //1.1通过反射获取pet对象。默认调用无参构造
      Pet pet=cls.newInstance();
      System.out.println(pet);
   //2,通过Class对象,获取构造函数对象(数组)
   Constructor[] constructor=cls.getDeclaredConstructors();
   for(Constructor cs:constructor){
    System.out.println(cs);//遍历所有构造函数
   }
   
   //2.1
      //获得单个带参构造函数
      Constructor<Pet> cs = cls.getConstructor(String.class,int.class,String.class);
      Constructor<Pet> cs1 = cls.getConstructor(null);//获得单个无参构造
      //通过获得的构造函数创建对象
      Pet p=cs.newInstance("张三",32,"红色");
      System.out.println("带参构造创建对象: "+p);
      Pet p1=cs1.newInstance(null);//通过获得的构造函数创建对象
      System.out.println("无参构造创建对象:  "+p1);
    //3.通过Class对象,获得属性对象Field   (要指定属性名)
     Field fname= cls.getDeclaredField("name");
     System.out.println(fname);
     fname.set(p, "小习");//fname是属性名,p是对象名,小习是实参值
     Field fage= cls.getDeclaredField("age");
     fage.setAccessible(true);//设置让私有属性可以在外部访问
     fage.set(p, 18);
     System.out.println(p);
       //4。通过class对象,获得方法对象Method。(通过方法名和参数列表获取某个特定的方法) 
     Method m1 = cls.getDeclaredMethod("eat", null);
     m1.invoke(p, null);
     Method m2 = cls.getDeclaredMethod("eat", String.class);
     m2.invoke(p, "草");
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

}

 

第三:流相关的概念

 

输入输出流:通过java程序把数据保存到数据源中(文件,网络,数据库等),当修改信息的时候要把被保存到数据源中的信息在java程序中显示出来。
             键盘是标准输入设备,显示器是标准输出设备。
管道是二进制的
1.按方向分类:输入流和输出流
(1).数据从键盘(数据源)输入(读入)到java程序:输入流input(往内存放数据),将数据读入java程序(往内存中存取数据,反过来说是内存将数据读取出来)
自我理解:例如文件输入流,是把文件夹中的东西输入到java程序中,然后在运行出来给人看
(2).java程序中把数据保存到数据源:输出流output(从内存中往外读数据)
自我理解:是java程序将东西输出到文件夹里。然后文件夹里就有这个东西了
2.按节点分类:节点流和处理流
节点流:将java程序和数据源连接通(直接连接,内容没转换)
处理流:加快数据的传输速度(将数据先保存到这里,随时可以用),处理流就是把节点流套上,再次包装一下,转换成自己想要的形式,内容没变
3.按传输单位分为字节流和字符流
字节流:一个字节8个二进制位,一次输入输出8个二进制位,汉字至少两个字节,这里一次只能读半个字
字符流:一次必须读取一个完整的字符,如果我这个字符是四个字节(例如int类型),我一次就要读取四个字节

由大到小的顺序:Reader,inputStreamRead,fileReader

 

文件是一个能输入到java程序的,因此这里介绍文件。因此File类在java.io包下
File:封装某个目录或者文件.
mkdir:make创建的意思,dir是目录的意思:创建目录
createnewfile:创建文件。异常处理,是因为如果创建一个k盘的就有异常了
list方法:返回字符串数组。这个方法是针对目录的,找到目录下的文件或者文件夹(目录)的名字
listFiles方法:获取目录下的文件或者文件夹的对象

对文件的内容进行读写操作:
1,InputStream,抽象类,继承object,所有字节输入流的超类:他的子类FileInputStream(“文件”字节输入流,节点流(接通双方,拉一个管道))
   子类中的read方法:返回值是int,int表示读取的字节数据,如果到达末尾返回-1。read其实就是读取里面内容的二进制(编码),
  如果想看文件里的具体内容就把int强转成char类型,强转之后也有个缺点,就是能显示英文,但是出现中文乱码。
2.OutputStream,字节输出流的超类,抽象类:他其中一个子类是FileoutputStream(文件字节输出流,节点流)
  getBytes方法把返回值通过jdk解码了,因此显示的不是二进制而是具体的内容了
  子类中的write方法:write方法接收的是int类型的值,但是文件里的内容怎么可能都是int类型呢,由于char自动转换成int,因此其实就是接收char类型的,
   因此我们把文件里的数据(字符串组成)转化成char类型的数组,然后遍历fos.write(bt);这里的bt传入的char类型的,但是自动转换成int类型的了。
因此写入文件的中文内容也不会乱码,因为是int类型

 

总结:输入输出是以内存为标准判断的(以程序或者内存为参照物)
内存(个人认为是java程序)得到:输入
内存向外写:输出

 

第四:流相关的代码

 

1.有关创建文件、创建目录的相关方法。

public class test {


 public static void main(String[] args) {
  File file = new File("f:/test1\\sub/a.txt");
  System.out.println(file);//file的toString方法
  boolean flag=file.exists();//判断是否存在
  System.out.println(flag);
  if(flag==false){
   file.mkdirs();//创建目录
  }
  System.out.println(file.isDirectory());//判断是不是目录
  System.out.println(file.isFile());//判断是不是文件
  System.out.println(file.isAbsolute());//判断是不是绝对路径

 }

}

 

 

2.从本地磁盘中获取指定目录下的文件

public class TestFile {

 
 public static void main(String[] args) {
  File fdir = new File("f:/test/sub");//目录
  File file = new File("f:/test/sub/c.txt");//文件
  System.out.println("查看目录是否存在:"+fdir.exists());
  System.out.println("查看文件是否存在:"+file.exists());
     
         try {
    file.createNewFile();//如果没有这个文件就创建这个文件c.txt
    String [] f=fdir.list();//得到该目录下的所有东西(包括文件和目录(文件夹))
    for(String s:f){
     System.out.println(s);
    }
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
        }
          
         
         
         System.out.println("--------------------");
         File[] f = fdir.listFiles();//得到目录对象
         for(File fil:f){
          System.out.println(fil.getName());//转化成对象的名字
         }
         
         File[] f1 = fdir.listFiles();//得到目录对象      
 }

}

 

 

3.文件输入流:从本地磁盘输入到java程序(内存),相当于读的过程

public class TestInput {

 public static void main(String[] args) {
  File file = new File("f:/test/sub/a.txt");
  try {
   FileInputStream fis=new FileInputStream(file);
   int b=0;//注意别忘这句话,用来保存读取的二进制编码
   //遍历文件里的所有内容,当int值为-1的时候说明全部遍历完了
   while((b=fis.read())!=-1){//fis.read()方法返回的是int类型的值,其实就是文件的内容所对应的二进制数,也就是0-255之间 的数字
    System.out.println(b);//为了能看到文件中的内容,因此将b强转成char(一个)后能查看到字母,但是汉字就乱码了,因为char是一个字节,汉字至少要两个字节
    System.out.println((char)b);
   }
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
 }

}

 

4.文件输出流(相当于写的过程)

 

public class TestOutput {

 /** 
从java程序输出到控制台,因此在java代码中需要一个字符串
  */
 public static void main(String[] args) {
  File file=new File("f:/test/sub/c.txt");
  try {
   FileOutputStream fos=new FileOutputStream(file,true);//是否追加:是
   String str="java.lang.SecurityManager#checkWrite的算法发大水";
   byte[] b=str.getBytes();//char是字符,byte是字节
   for(byte bt:b){//byte字节,是一个字节
    System.out.println("控制台打印:"+bt);//控制台打印的时候乱码了
    //将指定的字节写入文件输出流,这里面的字节bt自动转化成int类型了,因此写入到文件中没有乱码(int是四个字节,汉字是两个字节,因此不会乱码)
     fos.write(bt);//内容写入了文件中,内容没有乱码,因为write接受的是int类型的值(bt是个byte(字节)类型,但自动转化成int了),因此是四个字节,能够保持汉字(两个字节),因此文件中没有出现中文乱码
   }                  //控制台打印的依然是二进制编码
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  

 }

}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics