泛型
什么是:
- 1、定义时通过一个标识,表示类型;
- 2、Jdk5.0之后添加的
没有会造成的问题:
-
1、类型不安全;
-
2、强制转换比较繁琐;
-
1、E: list中使用;用指定的类型去替换E;
-
2、Map中使用;
public class GenericityTest {
@org.junit.Test
public void test1(){
List list = new ArrayList();
list.add(1);
/* 类型不安全,转换异常 */
list.add("a");
}
@Test
public void test2(){
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
/* 指定类型后,只能添加Integer类型 */
}
@Test
public 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);
}
}
@Test
public 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;
}
@Override
public 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 {
@Test
public 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) {
}
@Test
public 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;
}
/* 有限制条件的通配符的使用 */
@Test
public 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;
}
@Test
public 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;
}
/* 测试通配符的读写 */
@Test
public 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之外不可以添加;
}
@Test
public 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 {
@Test
public void test1(){
/* 多态 */
Object obj = null;
String str = "";
obj = str;
/* 多态 */
Object[] obj2 = null;
String[] str2 = null;
obj2 = str2;
}
@Test
public void test2(){
ArrayList<Object> list = new ArrayList<>();
ArrayList<String> str = new ArrayList<>();
/* 泛型不可以 */
//list = str;
}
@Test
public void test3(){
Person<String> str = null;
Person<Integer> i = null;
/* 泛型不可以 */
//str = i;
}
@Test
public 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 {
@Test
public 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());
}
@Test
public 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 {
@Test
public 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());
/* 此时文件还不存在,手动在路径中创建文件后可见多属性 */
}
@Test
public 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());
}
@Test
public 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);
}
}
@Test
public 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);
}
@Test
public 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());
}
@Test
public 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("文件删除失败");
}
}
}
@Test
public 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);
}
@Test
public 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 {
@Test
public 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();
}
@Test
public 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();
}
}
}
@Test
public 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();
}
}
}
}