泛型
什么是:
- 1、定义时通过一个标识,表示类型;
- 2、Jdk5.0之后添加的
没有会造成的问题:
-
1、类型不安全;
-
2、强制转换比较繁琐;
-
1、E: list中使用;用指定的类型去替换E;
-
2、Map中使用;
public class GenericityTest {@org.junit.Testpublic void test1(){List list = new ArrayList();list.add(1);/* 类型不安全,转换异常 */list.add("a");}@Testpublic void test2(){ArrayList<Integer> integers = new ArrayList<>();integers.add(1);/* 指定类型后,只能添加Integer类型 */}@Testpublic void test3(){//HashMap<String, Integer> map = new HashMap<String, Integer>();HashMap<String, Integer> map = new HashMap<>(); //jdk7类型推断;map.put("Tom", 1);map.put("Jack", 2);Set<Map.Entry<String, Integer>> entries = map.entrySet();
// var entries = map.entrySet(); //10 => 1.10 之后的版本;Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();while (iterator.hasNext()){Map.Entry<String, Integer> entry = iterator.next();String key = entry.getKey();Integer value = entry.getValue();System.out.println(key + " === >" + value);}}@Testpublic void test4(){TreeSet<String> strs = new TreeSet<>();}
}
/** * @Discrition 没有类型标识,不是泛型类;*/
public class Son extends Person{public Son() {}public Son(Object o, int orderId) {super(o, orderId);}public Son(Object o) {super(o);}}
/** * @Discrition 没有不确定的类型,不是泛型类*/
public class Son2 extends Person<String>{
}
/** * @Discrition 继承父类的Type;延续类型;*/
public class Son3<T> extends Person<T>{public void show(T t){System.out.println(t);}
}
/*** @Date 2023/8/8 10:47* @Discrition 类型不同的泛型类;* 父类被指定后,构造器中的父类类型也就确定了;*/
public class Son4<E> extends Person<String> {E e;public Son4(E e) {this.e = e;}public Son4(String s, int orderId, E e) {super(s, orderId);this.e = e;}public Son4(String s, E e) {super(s);this.e = e;}/* 这个不是泛型方法 */public E getE() {return e;}/* 这个是泛型方法 */public <E> E method(E e){return null;}public <E> ArrayList<E> method2(E[] arr) {for(E e: arr){}return null;}
}
方法泛型
- 1、自定义泛型类、接口
- (1)格式:
- ①Class A{}
- ②Interface B{}
- (1)格式:
- 2、自定义泛型方法;
- (1)泛型指定时不可以使用基本数据类型,可以使用包装类
- (2)指明泛型类型后,则在泛型类中。
- (3)凡是使用泛型的位置,都需要替换为指定的泛型类型
- 3、继承:
- (1)继承后的子类如果,不添加泛型标识。则子类不是泛型类;
- (2)子类继承泛型父类时,可以指定父类的类型;Son2.java;
- 4、说明
- (1)如果不指明类型,则默认为Object接收。但是不等价于Object;
- (2)开发中,如果使用就一路用下去;
- (3)静态方法中不能使用泛型;不能声明静态泛型属性;异常类不能带泛型;
- (4)
Comparable接口,每个对象的比较方法都是实现的这个接口;
!!声明类
public class Person<T> {T t; //不确定的类型;int i;Person(){}Person(T t, int orderId){}public Person(T t) {this.t = t;}public void setT(T t) {this.t = t;}public void setI(int i) {this.i = i;}public T getT() {return t;}public int getI() {return i;}@Overridepublic String toString() {return "Person{" +"t=" + t +", i=" + i +'}';}
}
泛型方法:
- 1、publi E method(E e) {}
- 2、 泛型方法标识:用于在类型声明泛型;
- 3、在方法调用时,指定类型;
- 4、可以声明成静态的;因为是调用方法的时候才指定的类型;
场景:
- 1、DAO类;数据库访问对象;
- 2、内部封装了数据库内部表的增删改查操作;
- 3、(增删改查)CRUD
数据库中的表设计ORM思想;
通配符的使用:
- 1、符号:“?”
- 2、GenericTest3.java
public class GenericTest3 {@Testpublic void test1() {/* 通配符,不限制格式 */List<?> list = null;List<String> list1 = null;List<Integer> list2 = null;list = list1;list = list2;/* 通配符 */method(list1);method(list2);}public void method(List<?> list) {}@Testpublic void test2() {/* 获取值 */List<?> list = null;List<String> list1 = new ArrayList<>();list1.add("aa");list = list1;/* 确定的类型,可以进行强转 */String str = (String) list.get(0);System.out.println(str);/* 使用Object替代?,不确定的类型肯定是Object的子类 */Object str2 = list.get(0);System.out.println(str2);/* 带通配符的不能写入,无法确定类型 *///list.add(""); //对于add(java.lang.String), 找不到合适的方法/* 有个特例null */list.add(null);// 对于引用类型,有一个共同的值 null;}/* 有限制条件的通配符的使用 */@Testpublic void test4(){/*** ? extends A;* 可以理解为小于等于;* ? 通配符只能标识A类或者A的子类;不能标识其父类;*/List<? extends Person> list = null;List<Person> list1 = null;List<Son4> list2 = null;List<Object> list3 = null;list = list1;list = list2;//list = list3;}@Testpublic void test5(){/*** ? super A;* 可以理解为大于等于;* ? 通配符只能标识A类或者A的父类;不能标识其子类;*/List<? super Person> list = null;List<Person> list1 = null;List<Son4> list2 = null;List<Object> list3 = null;list = list1;//list = list2;list = list3;}/* 测试通配符的读写 */@Testpublic void test6(){List<? extends Person> list = null;//(-∞, A] //没有下界,不能添加任何;List<Person> list1 = new ArrayList<>();list1.add(new Person());list = list1;/* 可以读取 */Person person = list.get(0);System.out.println(person);/* 写入数据 */list.add(null);//list.add(new Person<>());// 除了null之外不可以添加;}@Testpublic void test7(){List<? super Person> list = null;// [A, +∞) //有下界限;没有上界,子类都可以写入;List<Person> list1 = new ArrayList<>();list1.add(new Person());list = list1;/* 可以读取 */Object person = list.get(0); //只能使用object来接收;System.out.println(person);/* 写入数据 */list.add(null);list.add(new Person<>());//list.add(new Object()); //list.add(new Son());}
}
- 3、获取数据: test2;需要使用Object接收;
- 4、写入数据: 通配符的不可以写入,(null除外)
泛型方法的标识,写在返回值类型的前面;(有可能返回值类型=也是泛型,不能搞混)
有限制条件的通配符:
- 1、? Extends E ;相当于小于等于;?只能表示当前类,或者其子类通配符;
- 2、? Super E ;相当于大于等于;只能表示其本类或者父类的通配符;
- 3、GenericTest3.java中
- 4、
通配符读写能力
- 1、测试通配符的读写 代码:GenericTest3, => test6/7;
- 2、小技巧,直接往里写;让编译器给出提示;
- 3、extends
- (1)(-∞, A] //没有下界,不能添加任何;
- (2)除了null之外不可以添加;
- 4、super
- (1)[A, +∞) //有下界限;没有上界,子类都可以写入;
public class GenericTest2 {@Testpublic void test1(){/* 多态 */Object obj = null;String str = "";obj = str;/* 多态 */Object[] obj2 = null;String[] str2 = null;obj2 = str2;}@Testpublic void test2(){ArrayList<Object> list = new ArrayList<>();ArrayList<String> str = new ArrayList<>();/* 泛型不可以 *///list = str;}@Testpublic void test3(){Person<String> str = null;Person<Integer> i = null;/* 泛型不可以 *///str = i;}@Testpublic void test4(){Person<String> str = null;Person<String> str2 = null;str = str2;}
}
File类
Java.io.file
Java.io.xxx;**
FILE
- 1、文件或文件目录
- 2、实例
- (1) 绝对路径
- ①// 可以使用双斜杠 “\” 或者反斜杠“/”;
- ②File file1 = new File(“E:\E\javanote\test\project\file_io_2023815103542\src\main/hello.txt”);
- (2)相对路径
- (3)代码见FileTest.java;
- (1) 绝对路径
public class FileTest {@Testpublic void test1(){/* 绝对路径 */// 可以使用双斜杠 \\ 或者反斜杠/File file1 = new File("E:\\E\\javanote\\test\\project\\file_io_2023815103542\\src\\main/hello.txt");System.out.println(file1.getAbsoluteFile());/* 相对路径,使用junit和mian指向的路径是不一样的 */File file2 = new File("src"); //指定的是文件目录;System.out.println(file2.getAbsoluteFile());}@Testpublic void test2(){/* 路径下创建子文件或子文件目录 */File file1 = new File("E:\\E\\javanote\\test\\project\\file_io_2023815103542\\src\\main", "hello2.txt");System.out.println(file1.getAbsoluteFile());/* 参数2可可以是一个文件或者一个目录 */File hello2 = new File("src\\main", "hello3");/* 可以根据一个file类或者路径创建子 */File hello4 = new File(hello2, "hello4");}
}
- 3、方法
- (1)见代码FileMethod.java
public class FileMethod1 {@Testpublic void test1(){/* 文件方法 */File file1 = new File("abc.txt");System.out.println(file1.getName());System.out.println(file1.getPath());System.out.println(file1.getAbsoluteFile());System.out.println(file1.getAbsolutePath());System.out.println(file1.getParent());System.out.println(file1.getAbsoluteFile().getParent());System.out.println(file1.length());System.out.println(file1.lastModified());/* 此时文件还不存在,手动在路径中创建文件后可见多属性 */}@Testpublic void test2(){/* 路径方式 */File file2 = new File("src");System.out.println(file2.getName());System.out.println(file2.getPath());System.out.println(file2.getAbsoluteFile());System.out.println(file2.getAbsolutePath());System.out.println(file2.getParent());System.out.println(file2.getAbsoluteFile().getParent());System.out.println(file2.length()); //文件目录的方法这个获取不到;System.out.println(file2.lastModified());}@Testpublic void test3(){/* 目录的下一级 */File file1 = new File("src");/* 下一级的目录 */String[] list = file1.list();for(String str: list) {System.out.println(str);}System.out.println("====");/* 下一级的文件 */File[] files = file1.listFiles();for (File file : files) {System.out.println(file);}}@Testpublic void test4(){/* 重命名 */File file1 = new File("abc.txt");File file2 = new File("abc2.txt");/* rename的条件:file1存在,file2不存在;file2所在的目录要存在 */boolean bool = file1.renameTo(file2);System.out.println(bool);}@Testpublic void test5(){/* 判断方法 */
// File file1 = new File("abc2.txt");File file1 = new File("src");System.out.println(file1.exists());System.out.println(file1.isDirectory());System.out.println(file1.isFile());System.out.println(file1.canRead());System.out.println(file1.canExecute());System.out.println(file1.canWrite());System.out.println(file1.isHidden());}@Testpublic void test6() throws IOException {/* 创建删除文件 */// 删除不会进入回收站;// 删除目录,目录内必须为空;File file1 = new File("abcc.txt");if(!file1.exists()) {boolean iSSucceed = file1.createNewFile();if(iSSucceed){System.out.println("创建成功");} else {System.out.println("创建失败");}}else {System.out.println("文件已存在");boolean isDeleted = file1.delete();if(isDeleted){System.out.println("文件删除成功");}else {System.out.println("文件删除失败");}}}@Testpublic void test7(){/* 目录操作 */File file = new File("src\\test1"); //指定需要创建的目录File file2 = new File("src\\test2");boolean isSucceed = file.mkdir();System.out.println(isSucceed);/* mkdir 和 mkdirs 创建一层时一模一样 */boolean isSucceed2 = file2.mkdirs();System.out.println(isSucceed2);}@Testpublic void test8(){/* mkdirs 创建时会创建多层目录 */File file1 = new File("src\\test3\\test4");file1.mkdirs();File file2 = new File("src\\test2");file2.delete();}
}
File 类通常作为io流的端点存在;
IO流
- 字节流:
- 1、InputStream
- 2、OutputStream
- 字符流:
- 1、Reader
- 2、Write
需要了解的类,都是基于以上四个抽象基类;
使用
- //涉及到的刘非常多,但是用法基本都是一样的;
- FileWriter
- 代码:FileWriterReader.java;
- 一定要关闭操作;
- (使用try-catch-finally确保一定会关闭)
import org.junit.Test;import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;/*** @Date 2023/8/15 14:35* @Discrition*/
public class FileWriterReader {@Testpublic void test1() throws IOException {/* 创建文件对象 */File file = new File("reader.txt");/* 创建流 */FileReader reader1 = new FileReader(file);/* 读取的值是0-2的16次方 char类型*/int i = reader1.read();while (i > -1) {System.out.println(i);System.out.println((char) i);System.out.println("====");i = reader1.read();}reader1.close();}@Testpublic void test2() {/* 最好这样处理 */FileReader reader = null;try {/* 创建文件对象 */File file = new File("reader.txt");/* 创建流 */reader = new FileReader(file);/* 读取的值是0-2的16次方 */int i = reader.read();while (i > -1) {System.out.println(i);System.out.println((char) i);System.out.println("====");i = reader.read();}} catch (IOException e) {e.printStackTrace();} finally {try {if (reader != null) {reader.close();}} catch (IOException e) {e.printStackTrace();}}}@Testpublic void test3(){FileWriter writer = null;try {/* 写入流 */File file = new File("outPut.txt");/* 文件不在会自动生成文件,存在则覆盖之前的文件 */
// writer = new FileWriter(file, false);
// writer = new FileWriter(file); //默认就是false;/* 文件不在会自动生成文件,在现有的文件中追加内容 */writer = new FileWriter(file, true);writer.write(123);writer.write(12);writer.write("\n");writer.write("abc");writer.write("ab");writer.write("\n");writer.write("阿斯蒂芬");writer.write("\n");writer.write("阿斯蒂芬");} catch (IOException e) {e.printStackTrace();} finally {try {writer.close();} catch (IOException e) {e.printStackTrace();}}}
}