java笔记


Java 笔记

泛型:是一种把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,而这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口。
注意:一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。
1.    避免了类型强转的麻烦。
2.    它提供了编译期的类型安全,确保在泛型类型(通常为泛型集合)上只能使用正确类型的对象,避免了在运行时出现ClassCastException。
泛型虽然通常会被大量的使用在集合当中,但是我们也可以完整的学习泛型只是。泛型有三种使用方式,分别为:泛型类、泛型方法、泛型接口。将数据类型作为参数进行传递。
泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种集合框架容器类,如:List、Set、Map。
1.    泛型类的定义格式:
修饰符 class 类名<代表泛型的变量> { }


Io流
IO流用来处理设备之间的数据传输
* Java对数据的操作是通过流的方式
* Java用于操作流的类都在IO包中
* 流按流向分为两种:输入流(读取数据),输出流(写入数据)。
* 流按操作类型分为两种:
* 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
* 字符流 : 字符流只能操作纯字符数据,比较方便。
* 2.IO流常用父类
* 字节流的抽象父类:
* InputStream
* OutputStream
* 字符流的抽象父类:
* Reader
* Writer
* 3.IO程序书写
* 使用前,导入IO包中的类
* 使用时,进行IO异常处理
* 使用后,释放资源
Java I/O(输入和输出)用于处理输入并产生输出。
Java使用流的概念来加快I/O操作的速度。java.io软件包包含输入和输出操作所需的所有类。
我们可以通过Java I/O API 在Java中执行文件处理。
计算机中,任何的文字都是以指定的编码方式存在的,在 Java 程序的开发中最常见的是 ISO8859-1、GBK/GB2312、Unicode、 UTF 编码。

Java 中常见编码说明如下:

•    ISO8859-1:属于单字节编码,最多只能表示 0~255 的字符范围。
•    GBK/GB2312:中文的国标编码,用来表示汉字,属于双字节编码。GBK 可以表示简体中文和繁体中文,而 GB2312 只能表示简体中文。GBK 兼容 GB2312。
•    Unicode:是一种编码规范,是为解决全球字符通用编码而设计的。UTF-8 和 UTF-16 是这种规范的一种实现,此编码不兼容 ISO8859-1 编码。Java 内部采用此编码。
•    UTF:UTF 编码兼容了 ISO8859-1 编码,同时也可以用来表示所有的语言字符,不过 UTF 编码是不定长编码,每一个字符的长度为 1~6 个字节不等。一般在中文网页中使用此编码,可以节省空间。

在程序中如果处理不好字符编码,就有可能出现乱码问题。例如现在本机的默认编码是 GBK,但在程序中使用了 ISO8859-1 编码,则就会出现字符的乱码问题。就像两个人交谈,一个人说中文,另外一个人说英语,语言不同就无法沟通。为了避免产生乱码,程序编码应与本地的默认编码保持一致。

Java创建对象

方法1:new 一个对象
没对象就 new 一个吧,没错,使用 new 关键字,这也是 Java 创建对象最简单直接的方式了。
示例代码:
1
2
3
4
5    @Test
public void girlFriend1() {
    GirlFriend girlFriend = new GirlFriend("new一个对象");
    System.out.println(girlFriend);
}
输出结果:
GirlFriend(name=new一个对象)
方法2:克隆一个对象
朋友有女朋友,你没有,如果可以,把别人的女朋友克隆一个吧?
让女朋友类先实现 Cloneable 接口,并且实现其 clone() 方法:
1
2
3
4
5
6
7
8
9
10
11
12
13    @Data
@NoArgsConstructor
@AllArgsConstructor
class GirlFriend implements Cloneable {
  
 private String name;
  
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
     
}
注意:这里演示默认使用的是浅拷贝,即只克隆基本类型的字段,引用类型的需要再重写 clone() 方法手动赋下引用字段的值。
现在克隆一个对象,示例代码:
1
2
3
4
5
6    @Test
public void girlFriend2() throws CloneNotSupportedException {
    GirlFriend girlFriend1 = new GirlFriend("克隆一个对象");
    GirlFriend girlFriend2 = (GirlFriend) girlFriend1.clone();
    System.out.println(girlFriend2);
}
输出结果:
GirlFriend(name=克隆一个对象)
使用克隆的好处就是可以快速创建一个和原对象值一样的对象,对象的字段值一样,但是两个不同的引用。
方法3:类派发一个对象(反射)
直接使用女朋友类派发一个吧:
1
2
3
4
5
6    @Test
public void girlFriend3() throws InstantiationException, IllegalAccessException {
    GirlFriend girlFriend = GirlFriend.class.newInstance();
    girlFriend.setName("类派发一个对象");
    System.out.println(girlFriend);
}
输出结果:
GirlFriend(name=类派发一个对象)
方法4:动态加载一个对象(反射)
知道女朋友类在哪里(类全路径),但却没有被加载,那就反射一个对象吧:
1
2
3
4
5
6    @Test
public void girlFriend4() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    GirlFriend girlFriend = (GirlFriend) Class.forName("cn.javastack.test.jdk.core.GirlFriend").newInstance();
    girlFriend.setName("反射一个对象");
    System.out.println(girlFriend);
}
输出结果:
GirlFriend(name=反射一个对象)
方法5:构造一个对象(反射)
知道女朋友类的构造,就可以调用构造器构造一个对象:
1
2
3
4
5
6    @Test
public void girlFriend5() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    GirlFriend girlFriend = GirlFriend.class.getConstructor().newInstance();
    girlFriend.setName("构造一个对象");
    System.out.println(girlFriend);
}
输出结果:
GirlFriend(name=构造一个对象)
这里也可以同时结合类全路径构造一个对象。
方法6:反序列化一个对象
这个和克隆的作用类似,假如以前序列化(保存)了一个女朋友在磁盘上,现在就可以反序列化出来。
首先让女朋友可序列化,实现 Serializable 接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15    @Data
@NoArgsConstructor
@AllArgsConstructor
class GirlFriend implements Cloneable, Serializable {
  
    private static final long serialVersionUID = 1L;
     
    private String name;
  
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
  
}

Java File类常用方法

  1、createNewFile方法

  public boolean createNewFile() throws IOException

  该方法的作用是创建指定的文件。该方法只能用于创建文件,不能用于创建文件夹,且文件路径中包含的文件夹必须存在。

     2、delete方法

  public boolean delete()

  该方法的作用是删除当前文件或文件夹。如果删除的是文件夹,则该文件夹必须为空。如果需要删除一个非空的文件夹,则需要首先删除该文件夹内部的每个文件和文件夹,然后在可以删除,这个需要书写一定的逻辑代码实现。

  3、exists方法

  public boolean exists()

  该方法的作用是判断当前文件或文件夹是否存在。

  4、getAbsolutePath方法

  public String getAbsolutePath()

  该方法的作用是获得当前文件或文件夹的绝对路径。例如c: est1.t则返回c: est1.t.

  5、getName方法

  public String getName()

  该方法的作用是获得当前文件或文件夹的名称。例如c: est1.t,则返回1.t.

  6、getParent方法

  public String getParent()

  该方法的作用是获得当前路径中的父路径。例如c: est1.t则返回c: est.

  7、isDirectory方法

  public boolean isDirectory()

  该方法的作用是判断当前File对象是否是目录。

  8、isFile方法

  public boolean isFile()

  该方法的作用是判断当前File对象是否是文件。

  9、length方法

  public long length()

  该方法的作用是返回文件存储时占用的字节数。该数值获得的是文件的实际大小,而不是文件在存储时占用的空间数。

  10、list方法

  public String[] list()// 并不包含其属性。

  该方法的作用是返回当前文件夹下所有的文件名和文件夹名称。说明,该名称不是绝对路径。

  11、listFiles方法

  public File[] listFiles()

  该方法的作用是返回当前文件夹下所有的文件对象。包含其属性。

  12、mkdir方法

  public boolean mkdir()

  该方法的作用是创建当前文件文件夹,而不创建该路径中的其它文件夹。假设d盘下只有一个test文件夹,则创建d: estabc文件夹则成功,如果创建d:a文件夹则创建失败,因为该路径中d:a文件夹不存在。如果创建成功则返回true,否则返回false。

  13、mkdirs方法

  public boolean mkdirs()

  该方法的作用是创建文件夹,如果当前路径中包含的父目录不存在时,也会自动根据需要创建。

  14、renameTo方法

  public boolean renameTo(File dest)

  该方法的作用是修改文件名。在修改文件名时不能改变文件路径,如果该路径下已有该文件,则会修改失败。

  15、setReadOnly方法

  public boolean setReadOnly()

  该方法的作用是设置当前文件或文件夹为只读。

  16、File(String pathname)

  public File(String pathname)

  可以使用绝对路径也可以使用相对路径。

  17、File(String parent, String child)

  public File(String parent, String child)
Java 复制文件 - 流
这是java中文件复制的常规方式。在这里,我们创建两个文件 - 源和目标。然后我们从源创建InputStream并使用OutputStream将其写入目标文件进行 java 复制文件操作。这是可用于使用流的java复制文件的方法。
private static void copyFileUsingStream(File source, File dest) throws IOException {
    InputStream is = null;
    OutputStream os = null;
    try {
        is = new FileInputStream(source);
        os = new FileOutputStream(dest);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = is.read(buffer)) > 0) {
            os.write(buffer, 0, length);
        }
    } finally {
        is.close();
        os.close();
    }
}


RandomAccessFile简介
RandomAccessFile既可以读取文件内容,也可以向文件输出数据。同时RandomAccessFile 支持“随机访问”的方式,程序快可以直接跳转到文件的任意地方来读写数据。
•    由于RandomAccessFile可以自由访问文件的任意位置,所以如果需要访问文件的部分内容,而不是把文件从头读到尾,使用RandomAccessFile将是更好的选择。
•    与OutputStream、Writer等输出流不同的是,RandomAccessFile允许自由定义文件记录指针,RandomAccessFile可以不从开始的地方开始输出,因此RandomAccessFile可以向己存在的文件后追加内容。如果程序需要向已存在的文件后追加内容,则应该使用RandomAccessFile。
•    RandomAccessFile的方法虽然多,但它有一个最大的局限,就是只能读写文件,
不能读写其他IO节点。
•    RandomAccessFile的一个重要使用场景就是网络请求中的多线程下载及断点续传。
两个构造方法,除了第一个参数不同,第二个参数相同;
public RandomAccessFile(String name, String mode){
        this(name != null ? new File(name) : null, mode);
}
public RandomAccessFile(File file, String mode){}
mode指定RandomAccessFile的访问模式:
1、"r":以只读方式打开。调用结果对象的任何 write 方法都将导致抛出
IOException。
2、"rw":打开以便读取和写入
3、"rws":打开以便读取和写入。相对于"w","rws"还要求对“文件的内容”或“元数据”的 每个更新都同步写入到基础存储设备。
4、"rwd:打开以便读取和写入,相对于pw",rwd"还要求对“文件的内容”的每
个更新都同步写入到基础存储设备。

记事本

package cn.tedu;
 
 import java.io.RandomAccessFile;
 import java.util.Scanner;
 
 /**
  * 简单的记事本案例 
  *1.程序启动在控制台输入一个文件名
  *2.针对这个文件进行读写操作 
  *3.使用循环让用户向记事本中写入字符串 
  *4.编码格式选择自己工具中使用的编码(不需要和我一致) 
  *5.不考虑换行问题,当用户在控制台中输入”exit“表示结束
  * @author cjn
  *
  */
 public class RAF_Note {
 
     public static void main(String[] args) throws Exception {
         Scanner scan = new Scanner(System.in);
         System.out.println("请输入一个文件名称:");
         String fileName = scan.nextLine();
         //对文件进行读写操作
         RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
         System.out.println("请输入内容,单独输入exit退出:");
         //支持用户多次输入记录的内容
         while (true) {
             //接收用户输入信息
             String message = scan.nextLine();
             //加一个终止判断,并且防止把终止的信息也写到文件中
             if ("exit".equalsIgnoreCase(message)) {
                 //结束循环,不让用户继续在文件中写内容
                 break;
             }           
             //字符串转换为字节数组,此处注意字符集的编码格式,与自己的软件一致,否则乱码
             byte[] data = message.getBytes("utf-8");
             //向文件中写出数据
             raf.write(data);
         }
         System.out.println("写出完毕!");
         //关闭资源
         //Scanner底层是流(public Scanner(InputStream source)
         //public final static InputStream in = null;
         //用完需要关闭资源      
         scan.close();
         raf.close();
     }
 }

1.    创建FileInPutStream类的时候需要在参数里面传入一个文件的位置
2.    read(byte[]b);方法是可以把文件里面的b.length个字节的数据读取出来
3.    read(byte[]b,int off,int len)方法,byte[]b指定目标数组,int off,指定停止读取时机,int len可以指定每次读取的字节数
public class Demo01  {
    public static void main(String[] args) throws Exception {
        FileInputStream F1 = new FileInputStream("F:\\测试\\新建文本文档.txt");
        //读取一个字节的数据
        F1.read();
        //读取多个字节
        byte[] b = new byte[1024];
        int count = 0;
        while ((count=F1.read(b))!=-1){
            System.out.println(new String(b,0,count));
        }
        //关闭
        F1.close();
    }
}

1.定义一个方法,参数是HashMap集合用来统计次数和File对象要统计的文件夹
2.遍历File对象,获取它下边的每一个文件和文件夹对象
3.判断当前File对象是文件还是文件夹
4.如果是文件,判断这种类型文件后缀名在HashMap集合中是否出现过
没出现过,将这种类型文件的后缀名存入集合中,次数存1
出现过,获取这种类型文件的后缀名出现的次数,对其+1,在存回集合中
5.如果是文件夹,递归调用自己,HashMap集合就是参数集合,File对象是当前文件夹对象。
public static void main(String[] args) {
        Map<String ,Integer> map = new HashMap<>();//定义一个HashMap集合用来存储文件类型和个数
        getFile(map,new File("F:\\a"));//调用自己写的递归方法

        for(Map.Entry en :map.entrySet()){//遍历HashMap集合,打印出统计信息
            System.out.println("后缀名为“"+en.getKey()+"”的文件有"+en.getValue()+"个");
        }

    }

public static void getFile(Map<String,Integer> map,File path){
        if(path.isFile()){//判断file是否是文件
            String name = path.getName();//拿到文件名
            int i = name.lastIndexOf(".");
            String hzm ="";//定义一个变量用来存储后缀名
            if(i==-1){
                hzm ="无后缀名";
            }else {
                hzm = name.substring(i+1);//截取后缀名
            }
           //将后缀名和次数存入HashMap集合
            if(map.containsKey(hzm)){//如果该后缀名集合中存在,将次数加1之后再存储
                map.put(hzm,map.get(hzm)+1);
            }else {//如果集合中不存在该后缀名,直接存储后缀名,次数为1
                map.put(hzm,1);
            }
            
        }else {//如果不是文件名,是文件夹
            File[] files = path.listFiles();//得到文件夹的数组
            for(File file : files){
                if(file!=null)//数组的每一个元素都作为参数调用本方法,进行递归调用;
                getFile(map,file);
            }
        }
    }
Java FileOutputStream类
定义
public FileOutputStream(String name)
public FileOutputStream(File file)
public FileOutputStream(File file,boolean append)
public FileOutputStream(FileDescriptor fdObj)
参数
file:要打开以进行写入的文件。append:是否往文件中添加数据。
异常
FileNotFoundException:无法创建或者操作文件
SecurityException:无权限操作此文件
方法
//将指定的字节写入管道输出流。
public void write(int b)
public void write(byte[] b,int off,int len)
//返回与此文件输出流关联的唯一FileChannel对象。
public FileChannel getChannel()
//返回与此流关联的文件描述符。
public final FileDescriptor getFD()
//关闭输出流
public void close()
例子
public static void main(String[] args)
{
    OutputStream fs = null;
    try
    {
        StringBuffer buf = new StringBuffer();
        buf.append("Hello JAVASCHOOL!").append("\r\n");
        buf.append("Hello www.51gjie.com").append("\r\n");
        fs = new FileOutputStream(new File("c:\\51gjie.txt"), true)
        fs.write(buf.toString().getBytes())
    }
    catch(Exception e)
    {}
    finally
    {
        fs.close();
    }
}
1. FileOutputStream是文件字节输出流,它把内存中的数据写入到硬盘的文件中,一般用于向文件进行写入操作。
2. FileOutputStream默认会覆盖原文件数据,如果要在文件后面添加数据,append一定要设置成true。
3. 使用完流之后,要进行关闭,否侧会占用JVM的一定资源。


Java PrintWriter类
PrintWriter 是字符类型的打印输出流,它继承于Writer。它用于向文本输出流打印对象的格式化表示形式。它实现在 PrintStream 中的所有 print 方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。
构造函数
PrintWriter(File file)       使用指定文件创建不具有自动行刷新的新 PrintWriter。   
PrintWriter(File file, String csn)       创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。   
PrintWriter(OutputStream out     根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。   
PrintWriter(OutputStream out, boolean autoFlush)     通过现有的 OutputStream 创建新的 PrintWriter。   
PrintWriter(String fileName)    创建具有指定文件名称且不带自动行刷新的新 PrintWriter。   
PrintWriter(String fileName, String csn)    创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。   
PrintWriter(Writer out)     创建不带自动行刷新的新 PrintWriter。   
PrintWriter(Writer out, boolean autoFlush)      创建新 PrintWriter。   
关键字
protected Writer out;   传入的底层字符输出流  
private boolean autoFlush = false;      是否自动刷新  
private boolean trouble = false;    是否抛异常     
private Formatter formatter;    格式化类  
private PrintStream psOut = null;       字节打印流、用于checkError方法  
缓冲流:作用:为了提高数据传出效率,调高读写效率;
缓冲流,也叫高效流,是对4个基本的FileXxx 流的增强,所以也是4个流,按照数据类型分类:
•    字节缓冲流:BufferedInputStream,BufferedOutputStream
•    字符缓冲流:BufferedReader,BufferedWriter
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
1.2 字节缓冲流
构造方法
•    public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。
•    public BufferedOutputStream(OutputStream out): 创建一个新的缓冲输出流。
构造举例,代码如下:
    // 创建字节缓冲输入流
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
    // 创建字节缓冲输出流
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
复制 
public class Demo04 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("day10.zip");
        FileOutputStream fos = new FileOutputStream("day10_copy.zip");
        
        int len = -1;
        long start = System.currentTimeMillis();
        while((len = fis.read())!=-1) {
            fos.write(len);
        }
        long end = System.currentTimeMillis();
        System.out.println("复制完毕,耗时:"+(end-start)+"s");
        bis.close();
        bos.close();
    }
}
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值