继承,抽象类
public abstract class Animal {
private String name;
private int age;
public abstract void say();
}
public class Cat extends Animal{
@Override
public void say() {
System.out.println("喵喵叫");
}
}
public class Dog extends Animal{
@Override
public void say() {
System.out.println("汪汪叫");
}
}
public class Test {
public static void main(String[] args) {
Animal a1 = new Cat();
Animal a2 = new Dog();
a1.say();
a2.say();
}
}
多态
// 多态:父类引用指向子类对象
Collection<String> c = new ArrayList<>();
//1.创建一个Arraylist集合对象(有序,可重复,有索引)
ArrayList<String>list =new ArrayList<>();
//多态:list<String>list =new Arraylist<>();
//public void add(int index ,E element):在某个索引位置插入元素
//注意:集合大小之外的位置方元素,会抛异常
list.add("java1");
list.add("java2");
System.out.println(list);
//public E remove(int index):根据索引删除元素,返回被删除元素
list.remove(0);
System.out.println(list);
//public E get(int index):返回集合中指定位置的元素
list.add("java3");
list.add("java4");
list.add("java5");
list.get(3);
System.out.println(list);
//public E set(int index,E element):修改索引位置处的元素,修改成功后,会返回原来的数据
list.set(3,"jiawa");
System.out.println(list);
匿名内部类
public interface Calcular {
int calculate(int a, int b);
}
public class Test {
public static void main(String[] args) {
Calcular c = new Calcular() {
@Override
public int calculate(int a, int b) {
return a + b;
}
};
int sum = c.calculate(1, 2);
System.out.println(sum);
}
}
拼接字符串
public class StudentInfoTest { public static void main(String[] args) { Scanner scanner = new Scanner(System.in);
System.out.print("请输入学生姓名:");
String name = scanner.next();
System.out.print("请输入学生学号:");
String id = scanner.next();
System.out.print("请输入学生年龄:");
int age = scanner.nextInt();
/*
* 控制台打印
* 姓名:张三, 学号:007, 年龄:18
* 这样的格式
* */
StringBuilder sb = new StringBuilder();
sb.append("姓名:").append(name).append(", 学号:").append(id).append(", 年龄:").append(age);
System.out.println(sb);
}
迭代器
Iterator<Integer>it=list.iterator();
while (it.hasNext()){
Integer integer= it.next();
System.out.println(integer);
}
Integer 是int 的包装类
ArrayList<Integer> list = new ArrayList<>();
list.add(1);//自动装箱
list.add(2);
list.add(3);
//for循环
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//迭代器
Iterator<Integer>it=list.iterator();
while (it.hasNext()){
Integer integer= it.next();
System.out.println(integer);
}
//增强for循环
for (Integer integer : list) {
System.out.println(integer);
}
//foreach遍历,可以先用匿名内部类,再通过idea变成lambda或方法引用
//ctrl+q:看方法详细信息
list.forEach(System.out::println);
}
}
Date转日期格式字符串
public class Test {
public static void main(String[] args) {
Date date = new Date();
// 控制台打印 yyyy-MM-dd HH:mm:ss 格式的字符串
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = sdf.format(date);
System.out.println(format);
}
}
日期格式字符串转Date
public class Test {
public static void main(String[] args) throws ParseException {
// 通过以下字符串,得到一个Date对象,打印Date对象的时间毫秒值(时间戳)
String dateStr = "2012-12-21 12:34:11";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(dateStr);
long time = date.getTime();
System.out.println(time);
}
}
List4种遍历方式
public static void main(String[] args) {
// Integer 是 int 的 包装类
List<Integer> list = new ArrayList<>();
list.add(1); // 自动装箱
list.add(2);
list.add(100);
//(1)for循环
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//(2)迭代器。
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
Integer integer = iterator.next();
System.out.println(integer);
}
//(3)增强for循环
for (Integer i : list) {
System.out.println(i);
}
//(4)foreach遍历
// ctrl + Q:看方法详细信息
list.forEach(System.out::println);
}
List、Set、Map遍历
public class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Collections.addAll(list, "java1", "java2", "java3");
// 遍历集合,打印每个元素
for (String s : list) {
System.out.println(s);
}
Set<String> set = new HashSet<>();
Collections.addAll(set, "java1", "java2", "java3");
// 遍历集合,打印每个元素
set.forEach(s -> System.out.println(s));
Map<String, Integer> map = new HashMap<>();
map.put("西湖", 100);
map.put("湘湖", 10);
map.put("黑马", 1000);
// 遍历集合,打印每个元素
map.forEach((k, v) -> System.out.println("k=" + k + "v=" + v));
}
队列
//队列:先进先出
LinkedList<String> queue = new LinkedList<>();
//入队
queue.addLast("一号选手");
queue.addLast("二号选手");
queue.addLast("三号选手");
queue.addLast("四号选手");
System.out.println(queue);
//出队
System.out.println(queue.removeFirst());
System.out.println(queue.removeFirst());
System.out.println(queue.removeFirst());
System.out.println(queue);
栈
LinkedList<String> stack = new LinkedList<>();
//压栈
stack.push("第一颗子弹");
stack.push("第二颗子弹");
stack.push("第三颗子弹");
stack.push("第四颗子弹");
System.out.println(stack);
//弹栈
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack);
数组优缺点:查找快,增删慢 链表优缺点:查找慢,增删快
队列:先进先出
栈:先进后出
Set特点
public static void main(String[] args) { // Set<String> set = new HashSet<>(); // 无序、不重复、无索引 Set<String> set = new LinkedHashSet<>(); // 有序、不重复、无索引 set.add("张三"); set.add("李四"); set.add("王五"); set.add("王五"); set.add("赵六"); set.add("杨宁");
System.out.println(set);
// set.get() 没有,无索引
TreeSet<Integer> treeSet = new TreeSet<>(); // 排序、不重复、无索引
treeSet.add(12);
treeSet.add(11);
treeSet.add(100);
treeSet.add(100);
treeSet.add(50);
treeSet.add(99);
System.out.println(treeSet);
}
hashCode
//hashCode:对象的身份证
Student s1 = new Student("张三",18);
Student s2 = new Student("张三",18);
//同一个对象,多次调用hashCode()方法,获取的哈希值一样
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
//不同对象,哈希值极大概率不一样
System.out.println(s2.hashCode());
System.out.println("-------------");
//不同对象,极小概率生成的hashCode一样
String str1 =new String("ABC");
String str2 =new String("ABc");
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
/*
1.HashSet是集合.特点是无序,不重复,无索引
2.HashSet存对象,怎么让对象内容一样就认为重复呢?
3.HashSet底层是根据HashCode和equals方法,判断对象是否相等的
4.如果我们想让对象内容一样.放入HashSet就去重,需要重写HashCode和equals方法
*/
TreeSet
//TreeSet:排序,不重复,无索引
Set<Stundent> treeSet=new TreeSet<>();
Stundent s1=new Stundent("张三",19);
Stundent s2=new Stundent("张三",90);
Stundent s3=new Stundent("张三",190);
//TreeSet:添加对象元素时,对象需要实现Comparable接口
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
System.out.println(treeSet);
System.out.println("----------------");
TreeSet<String> treeSet1 =new TreeSet<>();
treeSet1.add("java1");
treeSet1.add("java2");
treeSet1.add("java3");
treeSet1.add("java4");
System.out.println(treeSet1);
System.out.println("----------------------"
);
Set<Integer>treeSet3=new TreeSet<>();
treeSet3.add(1);
treeSet3.add(2);
treeSet3.add(6);
treeSet3.add(3);
System.out.println(treeSet3);
遍历删除
//需要:找出集合中全部带"李"的名字,并从集合中删除.
List<String> list = new ArrayList<>();
list.add("蔡徐坤");
list.add("鸡哥");
list.add("李爱华");
list.add("李木子");
list.add("李玉刚");
list.add("李子");
// 输出
System.out.println(list);
//迭代器遍历删除:错误方法
// Iterator<String> it = list.iterator();
// while (it.hasNext()) {
// String name = it.next();
// if (name.contains("李")) {
// list.remove(name);
// }
// }
//迭代器遍历删除:正确方式
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String name = it.next();
if (name.contains("李")) {
//使用迭代器的remove()方法
it.remove();
}
}
System.out.println(list);
//普通遍历删除,漏删
// [王麻子,小李子,李爱花, 张全蛋,晓李,李玉刚]
// i=1,删除小李子 [王麻子,李爱花, 张全蛋,晓李,李玉刚]
// i=2 从张全蛋开始, 下标为一的李爱花就跳过了
// for (int i = 0; i < list.size(); i++) {
// String name = it.next();
// if (name.contains("李")) {
// list.remove(name);
// }
//
// }
//普通遍历删除,解决方式:remove方法后面i--
for (int i = 0; i < list.size(); i++) {
String name = list.get(i);
if (name.contains("李")) {
list.remove(name);
i--;
}
}
//普通遍历删除,从后往前遍历
for (int i = 0; i < list.size(); i--) {
String name = list.get(i);
if (name.contains("李")) {
list.remove(name);
}
}
//增强for循环报错,因为底层是迭代器
// for (String s : list) {
// if (s.contains("李")){
// list.remove(s);
// }
//
// }
//foreach报错,因为底层是迭代器
// list.forEach(new Consumer<String>() {
// @Override
// public void accept(String s) {
// if (s.contains("李")) {
// list.remove(s);
// }
// }
// });
可变参数
//计算两数的和
System.out.println(sum(1,2));
//3
System.out.println(sum(1,2,3));
System.out.println(sum(1,2,3,4,5,6,7));
}
public static int sum(int a, int... b) {
//方法体里面,可变参数int...b 变成了int[] b 数组
for (int i:b) {
a += i;
}
return a;
Collection工具类
ArrayList<Integer> list = new ArrayList<>();
// 1、public static <T> boolean addAll(Collections? super T> c, T...elements): 为集合批量添加数据
Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9);
System.out.println(list);
//2.public static void shuffle(List<?>list):打乱list集合中的元素顺序
Collections.shuffle(list);
System.out.println(list);
//3.public static<T> void sort(List<T>list):对list集合中的元素进行升序排序
Collections.sort(list);
System.out.println(list);
Collections.sort(list);
List<Student> student = new ArrayList<>();
//添加多个学生对象
Student s1 = new Student("张三", 1000);
Student s2 = new Student("张三", 90);
Student s3 = new Student("张三", 1800);
Student s4 = new Student("张三", 100);
Collections.addAll(student, s1, s2, s3, s4);
//代码实现年龄倒序排序:Comparable
Collections.sort(student);
System.out.println(student);
//@Override
// public int compareTo(Student o) {
// return o.age- this.age;
// }
// 代码实现年龄正序排序: Comparator
// Collections,sort(ListT> list, Comparator? super T> c)
Collections.sort(student, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
});
System.out.println(student);
}
}
class Student implements Comparable<Student> {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student o) {
return o.age-this.age;
}
Map工具类
//Map泛型有两个,分别代表key,value的数据类型
Map<String, Integer> map = new HashMap<>();//无序,不重复,无索引
//啤酒饮料矿泉水,花生瓜子八宝粥
map.put("啤酒",20);
map.put("饮料",8);
map.put("矿泉水",10);
//键值对:key value
map.put("花生",28);
map.put("瓜子",38);
map.put("八宝粥",50);
System.out.println(map);
//get(Object key)根据key,拿到value
Integer integer= map.get("花生");
System.out.println(integer);
//Map泛型有两个,分别代表key,value的数据类型 LinkedHashMap<String, Integer> map = new LinkedHashMap<>();//有序,不重复,无索引
//啤酒饮料矿泉水,花生瓜子八宝粥
map.put("啤酒",20);
map.put("饮料",8);
map.put("矿泉水",10);
//键值对:key value
map.put("花生",28);
map.put("瓜子",38);
map.put("八宝粥",50);
System.out.println(map);
//get(Object key)根据key,拿到value
Integer integer= map.get("花生");
System.out.println(integer);
TreeMap<Integer, String> treeMap = new TreeMap<>();//排序,不重复,无索引
treeMap.put(20,"java1");
treeMap.put(2,"java1");
treeMap.put(10,"java1");
treeMap.put(90,"java2");
treeMap.put(90,"java2");
treeMap.put(90,"java1");
treeMap.put(8,"java2");//判断key来看重复不重复
System.out.println(treeMap);
String s = treeMap.get(1);
HashMap<String, Integer> map = new HashMap<>();
//1.添加元素:无序,不重复,无索引.put
map.put("java",20);
map.put("php",30);
map.put("c++",40);
map.put("c+",60);
//2.public int size():获取集合的大小
System.out.println(map.size());
//3.public void clear():清空集合
// map.clear();
//4.public boolean isEmpty():判断集合是否为空,为空返回true,反之!
System.out.println(map.isEmpty());
//5.public V get(Object key):根据键获取对应值
System.out.println(map.get(20));
//6.public V remove(Object key):根据键删除整个元素(删除键会返回键的值)
System.out.println(map.remove(30));
//7.public boolean containsKey(Object key): 判断是否包含某个键 ,包含返回true ,反之
System.out.println(map.containsKey(40));
//8.public boolean containValue(Objec value):判断是否包含某个值
System.out.println(map.containsValue("c+"));
//9.public Set<K>keySet():获取Map集合的全部键
Set<String> keys = map.keySet();
System.out.println(keys);
//10.public Collection<V>values();获取Map集合的全部值
Collection<Integer> values = map.values();
System.out.println(values);
// 11.把其他Map集合的数据倒入到自己集合中来。(拓展)
Map<String, Integer> map1 = new HashMap<>();
map1.put("java1", 10);
map1.put("java2", 20);
Map<String, Integer> map2 = new HashMap<>();
map2.put("java3", 10);
map2.put("java2", 222);
map1.putAll(map2); // putAll:把map2集合中的元素全部倒入一份到map1集合中去。
System.out.println(map1);
System.out.println(map2);
HashMap<String, Integer> map = new HashMap<>();//有序,不重复,无索引
map.put("啤酒", 20);
map.put("饮料", 8);
map.put("矿泉水", 10);
map.put("花生", 28);
map.put("瓜子", 38);
map.put("八宝粥", 50);
//方法参数是抽象类,接口时:用匿名内部类
map.forEach(new BiConsumer<String, Integer>() {
@Override
public void accept(String s, Integer integer) {
System.out.println("key="+s+"value="+integer);
}
});
//通过idea把代码转为lambda形式
//shift+F6:更改光标指示的代码的名字
map.forEach((key, value) -> System.out.println("key=" + key + "value=" + value));
HashMap<String, Integer> map = new HashMap<>();//有序,不重复,无索引
map.put("啤酒", 20);
map.put("饮料", 8);
map.put("矿泉水", 10);
map.put("花生", 28);
map.put("瓜子", 38);
map.put("八宝粥", 50);
//Map集合的第二种遍历方式:获取键值对对象 Entry
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
for (Map.Entry<String, Integer> entry:entrySet){
System.out.println("key="+entry.getKey()+"value="+entry.getValue());
集合嵌套
/**
* 目标:理解集合的嵌套。
* 江苏省 = "南京市","扬州市","苏州市“,"无锡市","常州市"
* 湖北省 = "武汉市","孝感市","十堰市","宜昌市","鄂州市"
* 河北省 = "石家庄市","唐山市", "邢台市", "保定市", "张家口市"
*/
List<String> list1 = new ArrayList<>();
Collections.addAll(list1, "南京市", "扬州市", "苏州市", "无锡市", "常州市");
List<String> list2 = new ArrayList<>();
Collections.addAll(list2, "武汉市", "孝感市", "十堰市", "宜昌市", "鄂州市");
List<String> list3 = new ArrayList<>();
Collections.addAll(list3, "石家庄市", "唐山市", "邢台市", "保定市", "张家口市");
//集合嵌套,集合的一个元素是集合,最常见的集合嵌套:Map<String,List<String>>map =new HashMap<>();
Map<String, List<String>> map = new HashMap<>();
map.put("江苏省",list1);
map.put("湖北省",list2);
map.put("河北省",list3);
List<String>list=map.get("江苏省");
System.out.println(list);
Stream
LIst转map
list.stream()
.filter(student -> student.getAge()>=30)
.sorted(Comparator.comparingInt(Student::getAge))
.forEach(System.out::println);
编码解码
//1.编码:字符串变成byte[]
String s = "Ji坤坤";
byte[] bytes = s.getBytes();//默认是UTF-8编码格式
System.out.println(bytes);
byte[] bytes1 = s.getBytes("GBK");
System.out.println(Arrays.toString(bytes1));
//2.解码:byte[] 变成字符串
String s1 = new String(bytes);//默认是UTF-8
System.out.println(s1);
String s2 = new String(bytes1, "GBK");
System.out.println(s2);
//3.乱码:编码方式喝解码方式不同,会导致乱码(如果只有英文或数字`,不会代码)
String s3 = new String(bytes, "GBK");//UTF-8编,GBK解
System.out.println(s3);
String s4 = new String(bytes1);//GBK编,UTF-8解
System.out.println(s4);
IO流读取
FileInputStream读内容
// 1、创建文件字节输入流管道,与源文件接通
FileInputStream is = new FileInputStream("day08\\src\\comitheima\\d3\\itheima01.txt");
// 2、开始读取文件的字节数据。
// public int read(): 每次读取一个字节返回,如果没有数据了,返回-1.
/** int i = is.read();
System.out.println((char) i);//a
int i1 = is.read();
System.out.println((char) i1);b
*/
//固定写法
int b;
while ((b= is.read())!=-1){
System.out.print((char) b);
}
// 3、流使用完毕之后,必须关闭! 释放系统资源!
is.close();
FileInputStream 每次读取多个字节方法
// 1、创建一个字节输入流对象代表宇节输入流管道与源文件接通
FileInputStream is = new FileInputStream("D:\\heima\\javaSE\\day08\\src\\comitheima\\d3\\itheima01.txt");
// 2、开始读取文件中的字节数据: 每次读多个字节
// public int read(byte b[]) throws IOException
// 每次读取多个字节到字节数组中去,返回读取的字节数量,读取完毕会返回-1.
byte[] buffer = new byte[1024];//一般工作读[1024]
int len;
while ((len = is.read(buffer)) != -1) {
String s = new String(buffer, 0, len);
System.out.print(s);
}
//关闭链接
is.close();
FileInputStream 读取目标文件所有的数据
FileInputStream is = new FileInputStream("javaSE\\day08\\src\\comitheima\\d3\\itheima01.txt");
//readAllBytes():读取目标文件所有的数据
byte[] bytes = is.readAllBytes();
String s = new String(bytes);
System.out.println(s);
is.close();一定要记得关闭链接
FileInOutputStream写内容
//1.创建一个字节输出管道与目标文件接通
//注意:默认是覆盖
// FileOutputStream fos = new FileOutputStream("day08\\src\\comitheima\\d3\\itheima02.txt");
//public FileOutputStream(String name,boolean append):append=true,代表追加
// FileOutputStream fos = new FileOutputStream("day08\\src\\comitheima\\d3\\itheima02.txt");
FileOutputStream fos = new FileOutputStream("day08\\src\\comitheima\\d3\\itheima02.txt",true);
//write()方法,写入数据
fos.write('W');
fos.write('E');
fos.write('R');
//写多个字节
String s="鸡你太美哦baby";
fos.write(s.getBytes());
//限制写十个字节
fos.write(s.getBytes(),0,10);
//写特殊符号
fos.write("\n\r".getBytes());//\n是换行\r是空格
//关闭连接
fos.close();
复制图片
字节流
//需求:复制照片:把Ji.jpg照片复制出一个新的图片Jicopy.jpg
//一:创建字节输入流,读取数据
FileInputStream is = new FileInputStream("day08\\src\\comitheima\\d3\\Ji.jpg");
//二:创建字节输出流,写入数据
FileOutputStream fos = new FileOutputStream("day08\\src\\comitheima\\d3\\Jicopy.jpg");
//三:指定一个字节缓冲数组,一次读取1024个字节
byte[] bytes = new byte[1024];
//四:一次读取了多个字节
int len;
while ((len=is.read(bytes))!=-1){
//五:1.写入字节2.字节数组起始位置3.写多少个数据
fos.write(bytes,0,len);
}
//六:关闭流
is.close();
fos.close();
try-catch-finally
//认识try-catch-finally
//ctrl+alt+T:为包裹住的代码,生成try-catch-finally
try {
// System.out.println(10 / 0);//程序出错,finally也会执行
// System.out.println(10/2);//程序不出错,finally也会执行
// return;//return后,finally也会执行
// System.exit(0);//System.exit(0)后,finally不会执行
} catch (Exception e) {
e.printStackTrace();//idea自动生成
} finally {
System.out.println("finally执行了一次");
}
FileReader字符流
读取汉字(try-with-resoucre写法)
//try-with-resoucre写法,自动关流
try (
//创建FileReader对象,用于读取包含汉字的文件
FileReader reader = new FileReader("day09\\src\\comitheima\\d1\\666.txt");
) {
// int i=reader.read()
// System.out.println((char) i);
//创建一个char数组,每次读取1024个
char[] buffer = new char[1024];
int len;
while ((len = reader.read(buffer)) != -1) {
String s = new String(buffer, 0, len);
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace();
}
// reader.close();
写汉字文件(try-catch-finally写法)
FileWriter writer = null;
try {
// writer = new FileWriter("D:\\heima\\javaSE\\day09\\src\\comitheima\\d1\\666.txt",true);
writer = new FileWriter("D:\\heima\\javaSE\\day09\\src\\comitheima\\d1\\666.txt", true);
writer.write('A');
writer.write('隆');
writer.write("大傻逼坤坤6SB6");
String s = "大家看后代u快递跨行的跨行";
writer.write(s, 0, 13);
writer.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符流复制文本
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("day09\\src\\comitheima\\d1\\666.txt");
fw = new FileWriter("day09\\src\\comitheima\\d1\\666copy.txt");
char[] chars = new char[1024];
int len;
while ((len = fr.read(chars)) != -1) {
fw.write(chars, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fr != null) {
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fw != null) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
掌握字符缓冲输入流的用法
try (
//掌握字符缓冲输入流的用法
FileReader reader = new FileReader("day09\\src\\comitheima\\d2\\6.txt");
BufferedReader br = new BufferedReader(reader);
) {
/*
*经典写法:一次读1024个字符char[] buffer = new char[1024];
* int len;
while ((len = br.read(buffer)) != -1)
* {String s = new String(buffer,0, len);
* System.out.printIn(s);
*
*
*
* */
//BufferedReader独有方法:一次读一行
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (
Exception e) {
e.printStackTrace();
}
乱码转换
try (// 乱码代码演示,文件编码格式是GBK,而默认读取文件编码格式XUTF-8
//创建字节文件输入流
FileInputStream is = new FileInputStream("day09\\src\\comitheima\\d2\\abc.txt");
//创建输入转换流
InputStreamReader isr = new InputStreamReader(is, "GBK");
//把字符输入转换流放入新建的缓冲流中
BufferedReader br = new BufferedReader(isr);) {
String s;
while ((s = br.readLine()) != null)
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
写含汉字文件(try-catch-finally)
public class FileWriterTest2 {
public static void main(String[] args) {
FileWriter writer = null;
try {
// 掌握文件字符输出流:写字符数据出去
// FileWriter writer = new FileWriter("day09\\src\\itheima\\d1_char_stream\\novel.txt");
writer = new FileWriter("day09\\src\\itheima\\d1_char_stream\\novel.txt", true);
writer.write('A');
writer.write('龙');
writer.write("我TM写写写写写");
String s = "sh龙dbaidbi阿萨德吧上课的按时等不及哈巴三大";
writer.write(s, 0, 5);
// 刷新数据到文件中
writer.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
掌握字符输出转换流的作用
//掌握字符输入转换流的作用
try (
//创建一个文件字节输出流
FileOutputStream fos = new FileOutputStream("D:\\heima\\javaSE\\day09\\src\\comitheima\\d2\\abc.txt",true);
//把原始的字节输入流,按照指定的字符集编码转换成字符输出转换流(避免乱码)
OutputStreamWriter ows = new OutputStreamWriter(fos, "GBK");
//把字符输出转换流包装成缓冲字符输出流(效率更高)
BufferedWriter bw = new BufferedWriter(ows);
) {
bw.newLine();
bw.write("菜寻鲲练习两年半那急急急即将");
} catch (IOException e) {
e.printStackTrace();
}
翻译
InputStream 字节输入流
OutputStream 字节输出流
Reader 字符输入流
Writer 字符输出流
BufferedInputStream 字节缓冲输入流
BufferedOutputStream 字节缓冲输出流
BufferedReader 字符缓冲输入流
BufferedWriter 字符缓冲输出流
InputStreamReader 输入转换流
OutPutStreamWriter 输出转换流
序列化对象
public class Test {
public static void main(String[] args) {
//掌握对象字节输出流的使用:序列化对象
try (
//创建序列化输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day10\\src\\comitheima\\d1Object\\User.txt"));
) {
UserTest user = new UserTest("root", "10086", "菜寻鲲", 23);
System.out.println(user);
//writeObject方法:写入对象
oos.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
}
}
}
反序列读对象
public class TestUser {
public static void main(String[] args) {
//反序列读对象
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("day10\\src\\comitheima\\d1Object\\User.txt"));
//强转
UserTest userTest = (UserTest) ois.readObject();
userTest.setAge(100);
System.out.println(userTest);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//一个类实现了Serializable接口,就有序列化的能力
public class UserTest implements Serializable {
private static final long serialVersionUID = -5423792651855550607L;
private String loginName;
//transient:指定变量不会被序列化到文件中
private transient String passWord;
private String userName;
private int Age;
public UserTest() {
}
public UserTest(String loginName, String passWord, String userName, int age) {
this.loginName = loginName;
this.passWord = passWord;
this.userName = userName;
Age = age;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return Age;
}
public void setAge(int age) {
Age = age;
}
@Override
public String toString() {
return "UserTest{" +
"loginName='" + loginName + '\'' +
", passWord='" + passWord + '\'' +
", userName='" + userName + '\'' +
", Age=" + Age +
'}';
}
}
Properties文件解析
读取
public class Test {
public static void main(String[] args) throws IOException {
//1.创建一个Properties的对象出来(键值对集合,空容器)
Properties properties = new Properties();
//2.开始加载属性文件中的键值对数据到properties对象中去
properties.load(new FileReader("day10\\src\\comitheima\\Properties\\Test1.properties"));
//3.根据键取值
String name = properties.getProperty("name");
System.out.println(name);
//4.遍历全部的键和值
//写法一:匿名内部类写法
properties.forEach(new BiConsumer<Object, Object>() {
@Override
public void accept(Object o, Object o2) {
System.out.println("k=" + o + ",v=" + o2);
}
});
System.out.println("---------------------------");
//写法二:lambda写法
properties.forEach((k, v) -> System.out.println("k=" + k + ",v=" + v));
}
}
写入
public class Test2 {
public static void main(String[] args) throws IOException {
//1.创建Properties对象出来,先用它存储一些键值对数据
Properties properties = new Properties();
//2.properties设置key,value键值对
properties.setProperty("name","鸡哥");
properties.setProperty("age","120");
//3.把properties对象中的键盘对数据存入到属性文件中去
properties.store(new FileWriter("day10\\src\\comitheima\\Properties\\Test2.properties"),"I'm so handsome");
}
}
CommonsIO框架进行IO相关的操作
public class CommonsiIOTest {
public static void main(String[] args) throws IOException {
//使用CommonsIO框架进行IO相关的操作
//FileUtils
//文件拷贝
FileUtils.copyFile(new File("day10\\src\\comitheima\\d2\\Jicopy.jpg"),new File("day10\\src\\comitheima\\d2\\Ji_copy.jpg"));
//拷贝目录
FileUtils.copyDirectory(new File("D:\\heima\\javaSE\\day10\\src\\d2demo"),new File("D:\\heima\\javaSE\\day10\\src\\d2_demo"));
//删除目录
FileUtils.deleteDirectory(new File("D:\\heima\\javaSE\\day10\\src\\d2_demo"));
// IOUtils.closeQuietly优雅的关闭流,可变参数,把最外层的包装流传进去就行,可以多个参数
IOUtils.closeQuietly();
}
}
XML解析
public class xml {
public static void main(String[] args) throws DocumentException {
// 1、创建一个Dom4J框提供的解析器对象
SAXReader saxReader = new SAXReader();
// 2、使用saxReader对象把需要解析的XML 文件读成一个Document对象。
Document document = saxReader.read("day10\\src\\comitheima\\d3XML\\Test\\Test.xml");
//3、从文档对象中解析XML 文件的全部数据了
//getRootElement()返回根标签
Element root = document.getRootElement();
System.out.println(root.getName());
System.out.println("----------------------");
// 4、获取根元素下的全部一级子元素
List<Element> elements = root.elements();
elements.forEach(e -> {
System.out.println(e.getName());
});
System.out.println("--------------------");
// List<Element> elements = root.elements():
// 5、获取当前元素下的某个子元素
Element people = root.element("people");
System.out.println(people.getName());
// 如下面有很多子元素user,默认获取第一个。
Element user = root.element("user");
System.out.println(user.getName());
// 6、获取元素的属性信息呢?
String value = user.attributeValue("id");
System.out.println(value);
List<Attribute> attributes = user.attributes();
System.out.println("-----------------------");
for (Attribute attribute : attributes) {
System.out.println(attribute.getName() + " " + attribute.getValue());
}
System.out.println("--------------------------");
// 7、如何获取全部的文本内容: 获取当前元素下的子元素文本值
System.out.println(user.elementText("name"));
System.out.println(user.elementText("sex"));
System.out.println(user.elementText("地址"));
System.out.println(user.elementText("passwprd"));
System.out.println(user.elementTextTrim("地址"));//自动去掉空格
System.out.println(user.elementText("data"));
System.out.println(user.elementText("data2"));
}
}
线程
线程创建三种方式
继承Thread类
//1.继承Thread类型,就是一个自定义的线程类
public class MyThread extends Thread {
//重写run方法,写线程的执行任务
@Override
//重写run方法,写线程的执行任务
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程MyTherad输出:" + i);
}
}
}
public class ThreadTest1 {
//main方法是由一条默认的主线程负责执行
public static void main(String[] args) {
//3.创建MyThread线程类的对象代表一个线程
Thread myThread = new MyThread();
//4.start方法():启动线程(自动执行run方法的)
myThread.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程输出:" + i);
}
}
}
实现Runnable接口
//1.定义一个任务类,实现Runnable接口
public class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程Runnable执行:" + i);
}
}
}
public class ThreadTestRun {
public static void main(String[] args) {
//3.创建任务对象
MyRunnable myRunnable = new MyRunnable();
//4.任务对象交给一个线程对象处理
Thread thread = new Thread(myRunnable);
thread.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程执行:" + i);
}
}
}
实现Callable接口
// 1. 实现Callable接口,泛型指定为线程的返回值类型 public class MyCallable implements Callable<Integer> { private int start; private int end;
public MyCallable(int start, int end) {
this.start = start;
this.end = end;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = start; i <= end; i++) {
sum += i;
}
return sum;
}
}public class ThreadTest3 { public static void main(String[] args) throws ExecutionException, InterruptedException {
// 3、创建一个Callable的对象
Callable<Integer> c1 = new MyCallable(1, 10);
// 4、把Callable的对象封装成一个FutureTask对象(任务对象)
// 未来任务对象的作用?
// 1、是一个任务对象,实现了Runnable对象.
// 2、可以在线程执行完毕之后,用未来任务对象调用get方法获取线程执行完毕后的结果。
FutureTask<Integer> task1 = new FutureTask<>(c1);
// 5、把任务对象交给一个Thread对象
new Thread(task1).start(); Callable<Integer> c2 = new MyCallable(11, 20);
FutureTask<Integer> task2 = new FutureTask<>(c2);
new Thread(task2).start();
// 6、获取线程执行完毕后返回的结果。
// 注意:如果执行到这儿,假如上面的线程还没有执行完毕
// 这里的代码会暂停,等待上面线程执行完毕后才会获取结果。
Integer sum1 = task1.get();
Integer sum2 = task2.get();
int sum3 = 0;
for (int i = 21; i <= 30; i++) {
sum3 += i;
}
System.out.println("通过三个线程合力完成了这个" +
"复杂计算:1~30的和" + (sum1 + sum2 + sum3));
}
}
线程池
线程池创建
public class ThreadPoolTest2 { public static void main(String[] args) { // 核心线程数的设置 // 1. IO密集型 // CPU核数 X 2, 12X2=24 System.out.println(Runtime.getRuntime().availableProcessors());
// 2. CPU密集型
// CPU核数 + 1, 12+1=13
// 核心线程数的设置:和核心线程数相等、1.5倍、2倍
ExecutorService executor = new ThreadPoolExecutor(3, // 核心线程数
5, // 最大线程数
8, // 额外线程存活时间
TimeUnit.SECONDS, // 时间单位
new ArrayBlockingQueue<>(4), // 任务等待队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy());// 任务丢弃策略 (默认的报错的策略)
MyRunnable1 runnable1 = new MyRunnable1();
// 线程池自动创建新线程,自动处理这个任务
executor.execute(runnable1);
executor.execute(runnable1);
executor.execute(runnable1);
// 下面四个任务在等待队列中排队
executor.execute(runnable1);
executor.execute(runnable1);
executor.execute(runnable1);
executor.execute(runnable1);
// 创建临时(额外)线程,额外最多创建两个线程,因为最大线程数是5个
executor.execute(runnable1);
executor.execute(runnable1);
// 任务拒绝策略生效,AbortPolicy():是默认的拒绝策略,方式是报错
// executor.execute(runnable1);
// executor.shutdown(); // 线程池中所有任务执行完毕后,再关
// executor.shutdownNow(); // 强制关闭线程池,不管任务是否执行完毕
}
}
线程池工具类
public class ThreadPoolUtil {
private static final ExecutorService LOGIN_THREAD_POOL = new ThreadPoolExecutor(3, // 核心线程数
5, // 最大线程数
8, // 额外线程存活时间
TimeUnit.SECONDS, // 时间单位
new ArrayBlockingQueue<>(20), // 任务等待队列
Executors.defaultThreadFactory(), // 线程工厂
new ThreadPoolExecutor.AbortPolicy());// 任务丢弃策略 (默认的报错的策略)
public static void executeLoginJob(Runnable runnable) {
LOGIN_THREAD_POOL.execute(runnable);
}
}
public class ThreadDemo2 { public static final Logger LOGGER = LoggerFactory.getLogger(ThreadDemo2.class);
public static void main(String[] args) throws InterruptedException {
// 多个用户登录
// 改进:使用线程池管理线程,避免线程频繁创建
// 基于匿名内部类 --> lambda写法
ThreadPoolUtil.executeLoginJob(() -> login());
ThreadPoolUtil.executeLoginJob(() -> login());
ThreadPoolUtil.executeLoginJob(() -> login());
}
public static void login() {
long start = System.currentTimeMillis();
storeLoginMessage();
getAd();
checkAddress();
long end = System.currentTimeMillis();
LOGGER.info("共耗时:{}毫秒", (end - start));
}
private static void storeLoginMessage() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("记录登录信息-->用时500毫秒");
}
private static void getAd() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("广告推送-->用时1000毫秒");
}
private static void checkAddress() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("检测登录地址-->用时1000毫秒");
}
}
定义子类写法,匿名内部类
//掌握多线程创建方式二的匿名内部类写法
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("子线程1执行了:" + i);
}
}
}).start();
Thread thread = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("子线程2执行了:" + i);
}
});
thread.start();
for (int i = 0; i < 5; i++) {
System.out.println("主线程执行了:" + i);
}
}
}
public class ThreadTestRun3 {
public static void main(String[] args) {
// 创建两个子线程,一个用继承Thread的方式,一个用实现Runnable的方式
// 分别打印1~10、11~20,主线程打印21~30
ThreadTestRun3_Demo run3Demo = new ThreadTestRun3_Demo();
run3Demo.start();
new Thread(() -> {
for (int i = 11; i <= 20; i++) {
System.out.println("子线程Runnable:" + i);
}
}) .start();
for (int i = 21; i <= 30; i++) {
System.out.println("主线程:" + i);
}
}
}
public class ThreadTestRun3_Demo extends Thread {
@Override
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println("子线程Thread:"+i);
}
}
}
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//3.创建一个Callable的对象
Callable<Integer> c1 = new MyCallable(1,10);
// 4、把Callable的对象封装成一个FutureTask对象 (任务对象)
// 未来任务对象的作用?
// 1、是一个任务对象,实现了Runnable对象.
// 2、可以在线程执行完毕之后,用未来任务对象调用get 方法获取线程执行完毕后的结果.
FutureTask<Integer> task = new FutureTask<>(c1);
// 5、把任务对象交给一个Thread对象
new Thread(task).start();
Callable<Integer> c2 = new MyCallable(11,20);
FutureTask<Integer> task1 = new FutureTask<>(c2);
new Thread(task1).start();
// 6、获取线程执行完毕后返回的结果
// 注意:如果执行到这儿,假如上面的线程还没有执行完毕
// 这里的代码会暂停,等待上面线程执行完毕后才会获取结果。
int sum3 = 0;
for (int i = 21; i <= 30; i++) {
sum3 += i;
}
Integer sum1 = task.get();
Integer sum2 = task1.get();
System.out.println(sum1);
System.out.println(sum2);
System.out.println(sum3);
System.out.println("通过三个线程合力完成了这个总和="+(sum1+sum2+sum3));
}
}
// 1. 实现CalLable接口,泛型指定为线程的返回值类型
public class MyCallable implements Callable<Integer> {
private int start;
private int end;
public MyCallable(int start, int end) {
this.start = start;
this.end = end;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = start; i <= end; i++) {
sum += i;
}
return sum;
}
}
Junit单测
参考代码
public class Student { private String name; private int age; private double score;
public Student() {
}
public Student(String name, int age, double score) {
// 姓名检查
checkName(name);
this.name = name;
// 年龄检查
checkAge(age);
this.age = age;
checkScore(score);
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
// 改代码
checkName(name);
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
checkAge(age);
this.age = age;
}
public double getScore() {
return score;
}
public void setScore(double score) {
checkScore(score);
this.score = score;
}
private void checkName(String name) {
if (name == null) {
throw new IllegalArgumentException("名字不能为空");
}
if (name.length() > 4 || name.length() < 2) {
throw new IllegalArgumentException("名字必须2~4个字");
}
}
private void checkAge(int age) {
if (age > 100 || age < 15) {
throw new IllegalArgumentException("年龄需要在15到100岁");
}
}
private void checkScore(double score) {
if (score > 100 || score < 0) {
throw new IllegalArgumentException("成绩大于等于0,小于等于100");
}
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
package com.itheima.d1_junit;
import org.junit.Assert; import org.junit.Test; import org.junit.function.ThrowingRunnable;
public class StudentTest {
/*
* 分开写,每种情况分为一个测试方法
* */
@Test(expected = IllegalArgumentException.class)
public void testException1() {
// 1. 列举所有可能的异常创建学生对象情况 (name)
Student s2 = new Student(null, 18, 100);
}
@Test(expected = IllegalArgumentException.class)
public void testException2() {
// 1. 列举所有可能的异常创建学生对象情况 (name)
Student s3 = new Student("坤", 18, 100);
}
@Test(expected = IllegalArgumentException.class)
public void testException3() {
// 1. 列举所有可能的异常创建学生对象情况 (name)
Student s4 = new Student("张三李四王五田七", 18, 100);
}
@Test
public void testNormalStudentName() {
// 要求:学生名字不能为空,名字必须2~4个字
// 1. 列举所有可能已经创建出的学生对象
Student s1 = new Student("张三", 18, 100);
// 2. 使用Assert分别对创建的几个对象进行要求判断
Assert.assertNotNull(s1.getName()); // 判断一个对象不为空
int length = s1.getName().length();
Assert.assertTrue((length >= 2 && length <= 4));
}
/*
* 写在一个测试方法中
* */
@Test()
public void testStudentName() {
// 要求:学生名字不能为空,名字必须2~4个字
/*
* 第一部分:测试正常的创建
* */
// 1. 列举所有可能已经创建出的学生对象
Student s1 = new Student("张三", 18, 100);
// 2. 使用Assert分别对创建的几个对象进行要求判断
Assert.assertNotNull(s1.getName()); // 判断一个对象不为空
int length = s1.getName().length();
Assert.assertTrue((length >= 2 && length <= 4));
/*
* 第二部分:测试异常的创建
* */
Assert.assertThrows(IllegalArgumentException.class, () -> {
new Student(null, 18, 100);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
new Student("坤", 18, 100);
});
Assert.assertThrows(IllegalArgumentException.class, () -> {
new Student("张三李四王五田七", 18, 100);
});
}
@Test
public void testStudentAge() {
// 年龄是15到100岁
Student s1 = new Student("张三", 20, 100);
// 验证正常写法下,年龄是否有问题
Assert.assertTrue(s1.getAge() > 15 && s1.getAge() < 100);
// 验证创建不符合年龄要求的对象,
// 是否会抛出预期的IllegalArgumentException异常
Assert.assertThrows(IllegalArgumentException.class, new ThrowingRunnable() {
@Override
public void run() throws Throwable {
new Student("张三", 10, 100);
}
});
Assert.assertThrows(IllegalArgumentException.class,
() -> new Student("张三", 200, 100));
}
@Test
public void testStudentScore() {
// 成绩大于等于0,小于等于100
Student s1 = new Student("张三", 20, 80);
// 验证正常写法下,年龄是否有问题
Assert.assertTrue(s1.getScore() >= 0 && s1.getScore() <= 100);
// 验证创建不符合年龄要求的对象,
// 是否会抛出预期的IllegalArgumentException异常
Assert.assertThrows(IllegalArgumentException.class, new ThrowingRunnable() {
@Override
public void run() throws Throwable {
new Student("张三", 50, -100);
}
});
Assert.assertThrows(IllegalArgumentException.class,
() -> new Student("张三", 50, 300));
}
}
@Bofore &@After
public class JunitTest3 {
private FileInputStream is;
@Before
public void testBefore() throws FileNotFoundException {
// junit测试中,相对路径是从模块下的src目录开始
is = new FileInputStream("src\\com\\itheima\\qqq.txt");
}
@After
public void testAfter() throws IOException {
is.close();
}
@Test
public void test1() throws IOException {
int len;
while ((len = is.read()) != -1) {
System.out.print((char) len);
}
}
@Test
public void test2() throws IOException {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
String s = new String(buffer, 0, len);
System.out.println(s);
}
}
@Test
public void test3() {
System.out.println("我啥也没干");
}
}
统计文件file.txt中各个字母出现次数,文件内容如下
public class Test {
public static void main(String[] args) throws IOException {
FileInputStream is = new FileInputStream("homework\\src\\version2\\day10\\homework1\\file.txt");
byte[] buffer = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = is.read(buffer)) != -1) {
String s = new String(buffer, 0, len);
sb.append(s);
}
HashMap<Character, Integer> map = new HashMap<>();
char[] array = sb.toString().toCharArray();
for (char c : array) {
if (map.containsKey(c)) {
map.put(c, map.get(c) + 1);
} else {
map.put(c, 1);
}
}
}
}
冒泡排序
public class Test1 {
public static void main(String[] args) {
// 1、准备一个数组
int[] arr = {5, 2, 3, 1};
// 2、定义一个循环控制排几轮
for (int i = 0; i < arr.length - 1; i++) {
// i = 0 1 2 【5, 2, 3, 1】 次数
// i = 0 第一轮 0 1 2 3
// i = 1 第二轮 0 1 2
// i = 2 第三轮 0 1
// 3、定义一个循环控制每轮比较几次。
for (int j = 0; j < arr.length - i - 1; j++) {
// 判断当前位置的元素值,是否大于后一个位置处的元素值,如果大则交换。
if(arr[j] > arr[j+1]){
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
}
反射
现场测试
public class FieldTest {
@Test
public void getFields() throws NoSuchFieldException, IllegalAccessException {
//1.获取类的字节码对象
Class<Cat> clazz = Cat.class;
//2.获取所有己定义的变量
Field[] fields = clazz.getDeclaredFields();
//3.遍历数组,验证
for (Field field : fields) {
System.out.println(field.getName()+" "+field.getType());
}
System.out.println("------------------------------");
//4.获取指定的变量
Field name = clazz.getDeclaredField("name");
System.out.println(name.getName()+"-->"+name.getType());
//5.赋值
Cat cat = new Cat();
name.setAccessible(true);
name.set(cat,"傻猫");
System.out.println(cat);
//6.取值
String s=(String) name.get(cat);
System.out.println(s);
}
}
构造测试
public class ConstructorTest {
@Test
public void testConstructors() {
Class<Cat> clazz1 = Cat.class;
//getConstructors()作用:获取公开的构造方法
Constructor<?>[] con1 = clazz1.getConstructors();
for (Constructor<?> constructor : con1) {
System.out.println("参数名字: " + constructor.getName() + "参数个数: " + constructor.getParameterCount());
}
System.out.println("======================================================");
Constructor<?>[] con2 = clazz1.getDeclaredConstructors();
for (Constructor<?> constructor : con2) {
System.out.println("参数名字: " + constructor.getName() + "参数个数: " + constructor.getParameterCount());
}
}
@Test
public void testConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.获取字节码对象
Class<Cat> clazz1 = Cat.class;
// 2. getConstructor(CLass<?>... parameterTypes ) : 获取指定的公共构造方法
// ...代表可变参数
Constructor<Cat> con1 = clazz1.getConstructor();
// 3. newInstance(Object... initargs ): 通过构造方法创建对象
Cat cat = con1.newInstance();
System.out.println(cat);
}
@Test
public void testConstructor2() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.获取类对应的字节码对象
Class<Cat> clazz = Cat.class;
//2.getDeclaredConstructor:获取指定的构造方法
Constructor<Cat> con = clazz.getDeclaredConstructor(String.class,int.class);
System.out.println(con.getName()+con.getParameterCount());
//3.取消访问权限限制(即使private修饰,也可以使用)
con.setAccessible(true);
//4.newInstance(Object...initargs):通过构造方法创造对象
Cat cat = con.newInstance("傻逼", 5);
System.out.println(cat);
}
}
方法测试
public class MethodTest {
@Test
public void testMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1.获取类的字节码对象
Class<Cat> clazz = Cat.class;
//2.获取所有己定义的方法
Method[] methods = clazz.getDeclaredMethods();
//3.遍历打印每个方法的信息
for (Method method : methods) {
System.out.println(method.getName()+"--->"+method.getParameterCount()+"-->"+method.getReturnType());
}
//4.1获取指定的方法并运行
Method run = clazz.getDeclaredMethod("run");
Cat cat = new Cat();
run.invoke(cat);
//4.2获取指定的方法并运行
Method eat = clazz.getDeclaredMethod("eat", String.class);
eat.setAccessible(true);
eat.invoke(cat,"生可乐");
}
}
反射实现第一个框架
public class TestFrame {
public static void saveObjectToFile(Object obj) throws IllegalAccessException, IOException {
//创建Properties对象,用于写入Properties文件中
Properties properties = new Properties();
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 禁用权限检测
field.setAccessible(true);
// 获取变量名和变量值
String name = field.getName();
String value = String.valueOf(field.get(obj));
// 存入properties中
properties.setProperty(name, value);
}
// 要求:
// 传AStudent对象,写AStudent_store.properties文件
// 传入Cat象,写入Cat_store.properties文件
String fileName = clazz.getSimpleName() + "_store.properties";
// 写入文件
properties.store(new FileWriter(fileName), null);
}
}
public class ObjectFrame {
public static void main(String[] args) throws IOException, IllegalAccessException {
Cat cat = new Cat("傻猫", 3);
TestFrame.saveObjectToFile(cat);
Student student = new Student("张三",18);
TestFrame.saveObjectToFile(student);
}
}
KISS原则
代码的可读性和可维护性是衡量代码质量的两个重要标准。 而KISS原则就是保持代码可读和可维护的重要手段。 代码足够简单,也就意味着容易读懂,bug比较难隐藏。即便出现bug,修复也比较简单。
SOLID原则
单一职责原则
一个类或模块只负责完成一个职责(或功能)
开闭原则
添加一个新功能时应该是在已有代码基础上扩展代码(新增模块、 类和方法等),而非修改已有代码(修改模块、类和方法等)。
多态就是对开闭原则,最好的诠释
里氏替换原则
(使用父类对象的函数可以在不了解子类的情况下替换为使用子类对象)。
大白话就是,子类覆写父类的方法后,不应该做不符合父类方法本意的事情
接口隔离原则
接口隔离原则指导我们在设计接口时应该保持接口的粒度小、高内聚、不耦合,避免定义大而全的接口。
依赖反转原则
主要用来指导框架的设计
举例子: 一:我们写的动物类,应不应该关心某个具体子类如Cat类的方法?不应该,因为抽象不要依赖具体实现细节 应该是Cat作为具体实现类,依赖抽象类动物类。具体实现细节依赖抽象。(继承、抽象的知识点)
二:一个Java支付系统分为 用户-->订单-->对接银行 三个模块 用户是订单的上层,用户模块需要感知订单模块的细节吗?不需要,直接调用订单模块的方法就够了 订单模块是用户模块的下层,订单模块需要感知用户模块的细节吗?需要,不然订单模块就没法拿到需要的信息
订单-->对接银行的上下层关系同理
单列
建造者模式
public class User { private String username; private String password; private int age; //手机品牌 private String phone; //手机号 private String phoneNumber; public User(Builder builder) { this.username = builder.username; this.password = builder.password; this.age = builder.age; this.phone = builder.phone; this.phoneNumber = builder.phoneNumber; } //Builder建造者模式 // 只提供静态内部类Builder来创建User对象的方式 public static class Builder { private String username; private String password; private int age; //手机品牌 private String phone; //手机号 private String phoneNumber; public Builder setUsername(String username) { this.username = username; return this; } public Builder setPassword(String password) { this.password = password; return this; } public Builder setAge(int age) { this.age = age; return this; } public Builder setPhone(String phone) { this.phone = phone; return this; } public Builder setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; return this; } public User build() { // 参数校验逻辑,以后无论校验逻辑多复杂,都只聚焦在build(),便于维护 if (username == null) { throw new IllegalArgumentException("用户名不能为空"); } if (password == null) { throw new IllegalArgumentException("密码不能为空"); } if (age < 0 || age > 150) { throw new IllegalArgumentException("年龄必须在0~150之间"); } if (phone == null && phoneNumber != null) { throw new IllegalArgumentException("有手机号却没手机品牌异常"); } if (phone != null && phoneNumber == null) { throw new IllegalArgumentException("有手机品牌却没手机号异常"); } return new User(this); } } }
public class Demo { public static void main(String[] args) { // 写法:使用Builder为User对象赋值 User user = new User.Builder() .setUsername("张三") .setPassword("123") .setAge(18) .setPhone("苹果") .setPhoneNumber("110") // 只有用build()方法结尾,才返回User对象(无论如何都会走进我的校验中) .build(); User user0 = new User.Builder() .setUsername("张三") .setPassword("123") .setAge(18) .build(); // User user1 = new User.Builder() // .setUsername("张三") // .setPassword("123") // .setAge(18) // .setPhone("苹果") // .build(); // // User user2 = new User.Builder() // .setPassword("123") // .setAge(18) // .setPhone("苹果") // .setPhoneNumber("120") // .build(); } }