泛型
泛型:编译时检查类型是不是正确,减少类型转换造成的错误。
代码复用性提升。
1.泛型类
T是类型形参,创建对象时传入类型实参。
如果不指定类型,按照object类型处理。不支持基本数据类型。
class Student<T>{
private T age;
}
2.泛型类的子类
如果泛型类的子类也是泛型类,子类的泛型标志必须包含父类的标志。
例如 父类:Class Parent<T>{},子类:class Child<T,K> extends Parent<T>{}
如果泛型类的子类不是泛型类,子类要明确父类的泛型类型
例如:父类:Class Parent<T>{},子类:class Child extends Parent<String>{}
3.泛型接口
实现类不是泛型类,接口要明确数据类型。
例如:接口:Interface Imp<T> 实现:class Appl implements Imp<String>
实现类是泛型类,实现类包含接口的泛型。
例如:接口:Interface Imp<T> 实现:class Appl<K,T> implements Imp<T>
4.泛型方法
注意格式:public <T,K,V> T test(K k,V v){}和泛型类的成员方法不同的是有泛型列表。
泛型类的成员方法不能是静态方法,泛型方法可以是静态方法。(static修饰)
5.泛型通配符"?"
为什么要有泛型通配符
根据多态,传递的参数是类型的子类也可以,但是在泛型中不遵守继承。
如果指定泛型是object?由于泛型不支持继承多态
这时候就需要使用泛型通配符?表示可以传递任何类型。
泛型通配符的下界 : ?super 实参类型
泛型通配符的上界 : ? extend 实参类型
6.泛型编译的类型擦除
反射使用泛型,省去类型转换。
io流
流使用完要调用close方法关闭资源
File类
new File(String 路径)
exists()判断文件是否存在 isFile()是不是文件对象,isDirectory()是不是文件夹
getName()获取文件名 length()获取文件长度 lastModified()最后修改的时间
getPath()获取路径 getAbsolutePath绝对路径
mkdir()创建文件,只能创建一级文件 mkdirs()创建文件夹 delete()删除文件
遍历:list()获取子文件名 listFileds()获取子文件对象
字节流
输入流读取文件
new FileInputStream()输入流构造器,可以传递文件对象,也可以传递路径作为参数。
read()读取一个字节,返回读到的数据,当没有的时候返回-1
read(byte[])读取数组大小的字节,类似一个桶,返回每次读的长度。没有了返回-1.
存在覆盖问题。
public class Input {
public static void main(String[] args) throws IOException {
InputStream is1=new FileInputStream("D:\\javacode2\\工作区2\\learnSF\\src\\main\\java\\test.txt");
InputStream is2 = new FileInputStream(new File("D:\\javacode2\\工作区2\\learnSF\\src\\main\\java\\test.txt"));
int read1=0;
while (read1!=-1){
read1=is1.read();
if(read1==-1){
break;
}
System.out.print((char) read1);
}
System.out.println();
System.out.println("==================");
byte[] buffer=new byte[3];
int len2=0;
while (len2!=-1)
{ len2= is2.read(buffer);
if(len2==-1){
break;
}
String s= new String(buffer,0,len2);
System.out.print(s);
}
is1.close();
is2.close();
// ReadAllStream jdk9之后才有
}
}
一下子把文件内容全读出来:readallstream方法,内部实现就是创建一个足够大的byte数组当桶。如果目标文件过大,同样也会报错。
字符流
package IOStream;
import java.io.*;
public class Filerw {
public static void main(String[] args) throws IOException {
//字节输入流
Reader is=new FileReader("D:\\javacode2\\工作区2\\learnSF\\src\\main\\java\\test2");
Reader is2=new FileReader("D:\\javacode2\\工作区2\\learnSF\\src\\main\\java\\test2");
//read()一个一个字符读 read(char[]) 一桶一桶读
int a;
while ((a=is.read())!=-1){
System.out.print((char) a);
}
///
char [] b=new char[3];
int len;
while ((len=is2.read(b))!=-1){
System.out.print(new String(b,0,len));
}
is.close();
is2.close();
//字节输出流,要关闭流。因为java是写到内存的缓冲器,如果不关闭就不会将缓冲器的内容写到硬盘
Writer w1=new FileWriter("D:\\javacode2\\工作区2\\learnSF\\src\\main\\java\\hhh1.txt");
//以追加的形式写
Writer w2=new FileWriter("D:\\javacode2\\工作区2\\learnSF\\src\\main\\java\\hhh1.txt",true);
//write(int) write(String) write(String,off,len) write(char[]) write(char[],off,len)
w1.write("nihhhh");
w1.write("\r\n");
char[] c={'n','h','f','g','f','胡','金'};
w2.write(c);
//一定要关闭流
w1.close();
w2.close();
}
}
缓冲流
包装基本的字符、字节输入输出流
原来是将内存的数据直接写到硬盘中,多次系统调用,性能不好,现在在内存中增加了缓冲池,8KB,缓存池满了再和硬盘交互,减少系统调用,性能更好。
// BufferedInputStream 包装fileinputstream 需要fileinputstream 做构造器参数 // BufferedOutputStream 包装fileoutputstream 需要fileoutputstream 做构造器参数 // BufferedWriter 包装filewrite 需要filewrite做构造器参数。 换行方法:对象.newLine() // BufferedReader 包装fileread 需要fileread做构造器参数
转换流
utf-8每个汉字三个字节,GBK每个汉字两个字节
如果代码编码和读取文件编码不同,会乱码。
转换流的构造器需要字节流或者字节流的子类。