1.反射
就是通过另一个方式来获取类对象的信息
之前就是new Person();换一种反射的方式
Java可以将 .Java文件编译成 .class文件,这个class文件包含了类中所有的信息(属性,方法,构造方法)
.class文件会被加载(ClassLoader)到虚拟机中,可以通过.class文件获取类中的所有信息
1.1获取Class对象
三种方式进行获取
先获取Class对象才能获取类中的信息(属性,构造方法,方法)
package com.qf.day26;
//反射
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException {
//方式一
Class<Person> personClass = Person.class;
System.out.println(personClass);
//方式二
Class<? extends Person> aClass = new Person().getClass();
System.out.println(aClass);
//方式三
Class<?> aClass1 = Class.forName("class com.qf.day26.Person");
System.out.println(aClass1);
Class<?> aClass2 = Class.forName("class com.qf.day26.Person");
System.out.println(aClass2);
}
}
1.2获取Constructor对象
通过Class对象调用方法获取构造方法
Constructor<?>[] getConstructors()返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 方法 Constructor<?>[] getDeclaredConstructors()返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 。 Constructor getConstructor(类<?>… parameterTypes)返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。 Constructor getDeclaredConstructor(类<?>… parameterTypes)返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。
package com.qf.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Demo1 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<Person> personClass = Person.class;
//获取公开的构造方法
Constructor<?>[] constructors = personClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
//获取所有的方法
Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
System.out.println("+++++++++++++++++++++++");
//获取无参的构造方法
Constructor<Person> constructor = personClass.getConstructor(null);
System.out.println(constructor);
System.out.println("+++++++++++++++++++++++");
//获取有参的构造方法
Constructor<Person> constructor1 = personClass.getConstructor(String.class,int.class);
System.out.println(constructor1);
System.out.println("+++++++++++++++++++++++");
//获取无参的构造方法
Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor();
System.out.println(declaredConstructor);
System.out.println("+++++++++++++++++++++++");
//private Person (String name)
Constructor<Person> declaredConstructor1 = personClass.getDeclaredConstructor(String.class);
System.out.println(declaredConstructor1);
//借助于无参的构造出来一个对象
Person person = declaredConstructor.newInstance(null);
Person person1 = constructor1.newInstance("goudan", 12);
System.out.println(person1.name);
System.out.println(person1.age);
}
}
1.3获取Method对象
方法[] getMethods()返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。 方法[] getDeclaredMethods()返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。 方法 getMethod(String name, 类<?>… parameterTypes)返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法类对象。 方法 getDeclaredMethod(String name, 类<?>… parameterTypes)返回一个 方法对象,它反映此表示的类或接口的指定声明的方法类对象。
以上方法都是Class对象调用的
以下方法是Method对象调用
Object invoke(Object obj, Object …args);
使用方法对象调用invoke 方法会执行的
package com.qf.test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Demo3 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<Person> personClass = Person.class;
Method[] methods = personClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("==========================");
Method[] declaredMethods = personClass.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("=========================");
Method eat = personClass.getMethod("eat", String.class, int.class);
System.out.println(eat);
System.out.println("=========================");
//获得私有的方法
Method drank = personClass.getDeclaredMethod("drank",null);
System.out.println(drank);
//获取之后呢? 方法对象获取之后 方法调用
//Object invoke(Object obj, Object... args)
//第一个参数 是 此方法在哪个对象下面
//第二个参数 是方法有可能有参数,传的是实参
System.out.println("=========================");
Person person = personClass.getConstructor(null).newInstance(null);
//eat.invoke(person, null);
eat.invoke(person, "sb", 98);
drank.setAccessible(true);
drank.invoke(person, null);
}
}
1.4获取Field对象
Field[] getFields()返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段(属性) 类对象。 Field[] getDeclaredFields()返回的数组 Field对象反映此表示的类或接口声明的所有字段类对象。 Field getField(String name)返回一个Field对象,它反映此表示的类或接口的指定公共成员字段类对象。 Field getDeclaredField(String name)返回一个 Field对象,它反映此表示的类或接口的指定已声明字段类对象。
以上的方法是Class对象
以下是Field对象的方法
void set(Object obj, Object value) 将value值赋值给obj下面的属性
package com.qf.a_class;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class Demo4 {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class<Person> personClass = Person.class;
//获取所有的公开的属性
Field[] fields = personClass.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("=======");
//获取所有的属性对象
Field[] declaredFields = personClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("-------------");
//获取单个属性
Field name = personClass.getField("name");
System.out.println(name);
// Field age = personClass.getField("age");//这个报错不?
// System.out.println(age);
Field age = personClass.getDeclaredField("age");
System.out.println(age);
//属性获取完以后? 赋值
Person person = personClass.getConstructor(null).newInstance(null);
name.set(person, "狗蛋");//将狗蛋赋值给person 对象下面的 name属性
System.out.println(name.get(person));//在指定的对象下面获取 name属性值
// can not access a member
age.setAccessible(true);
age.set(person, 67);
System.out.println(age.get(person));
}
}
2.设计模式
java中20多种设计模式中,最重要的是的案例模式,代理模式等!
2.1单例模式
要求在整个运行程序中,同一个类只出现一个对象。目的减少内存的消耗。
如何查看对象同一个对象?看内存地址。如果内存地址一样就是一个对象。
加上线程安全的单例模式:
package com.qf.day26;
//线程安全的单例模式
class SingDog {
public static SingDog singDog;
//私有化构造方法
private SingDog() {
}
//静态方法
public static synchronized SingDog getInstance() {
if (singDog == null) {
singDog = new SingDog();
}
return singDog;
}
}
class MyThread1 implements Runnable {
@Override
public void run() {
SingDog instance = SingDog.getInstance();
System.out.println(instance);//对象的地址
}
}
class MyThread2 implements Runnable {
@Override
public void run() {
SingDog instance = SingDog.getInstance();
System.out.println(instance);
}
}
public class Demo5 {
public static void main(String[] args) {
SingDog instance = SingDog.getInstance();
//启动线程
new Thread(new MyThread1()).start();
new Thread(new MyThread2()).start();
}
}
懒汉式写法:
package com.qf.day26;
//单例模式
class People {
//静态变量
public static People people = null;
//封装的私有的构造方法
private People() {
}
//静态的方法,使用类名进行调用 ,不能使用对象来调用的 因为私有化构造方法了
public static People getInstance() {
if (people == null) {
people = new People();
}
return people;
}
}
public class Demo3 {
public static void main(String[] args) {
People instance = People.getInstance();
People instance1 = People.getInstance();
System.out.println(instance);
System.out.println(instance1);
}
}
饿汉式写法:
package com.qf.day26;
//饿汉式开发
class SingleCat {
//直接new, final修饰的常量
public static final SingleCat singleCat = new SingleCat();
//私有化构造方法
private SingleCat() {
}
//静态方法
public static SingleCat getInstance() {
return singleCat;
}
}
public class Demo4 {
public static void main(String[] args) {
}
}
懒汉式:线程不安全
饿汉式:线程是安全的,饿汉式的效率高,因为没有加锁,但是性能低。
性能:饿汉式类一加载就必须加载对象,但是懒汉式的当需要加载对象的是后面才会加载对象,才会去new
所以开发中常用的是懒汉式
3.Lambda表达式
lambda表达式被称为闭包。函数式编程,就是为了简化代码,让代码更加简洁。
入门案例:
package com.qf.day26;
//lambda表达式
public class Demo6 {
public static void main(String[] args) {
//前提条件:当接口下面只有一个抽象方法的时候 可以简写
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("哈哈");
}
};
//lambda表达式
Runnable runnable1 = () -> System.out.println("嘻嘻");
new Thread(runnable).start();
new Thread(runnable1).start();
}
}
3.1Lambda表达式的语法格式
函数式接口,接口下面有且只有一个抽象类,才能使用Lambda
无参无返回值 接口 接口对象 = ()-> 表达式 有参无返回值 接口 接口对象 = (parameter(参数))-> 表达式 无参有返回值 接口 接口对象 = ()-> {表达式;} 有参有返回值 接口 接口对象 = (parameter(参数))-> {表达式;}
3.2无参无返回值
接口 接口对象 = ()-> 表达式
package com.qf.day26;
interface A{
void eat();
}
public class Demo7 {
public static void main(String[] args) {
//无参无返回值 接口 接口对象 = ()-> 表达式
A a = ()-> System.out.println("吃饭");
test(a);
//简化
test(()-> System.out.println("吃饭啦"));
//一般是下面的情况
test(new A() {
@Override
public void eat() {
System.out.println("恰饭");
}
});
}
public static void test(A a){
a.eat();
}
}
3.3有参无返回值
接口 接口对象 = (parameter(参数))-> 表达式
package com.qf.day26;
//有参无返回值 接口 接口对象 = (parameter(参数))-> 表达式
interface B {
void eat(String name, int age);
}
public class Demo8 {
public static void main(String[] args) {
test((name, age) -> System.out.println(name + "的年龄是" + age), "二狗", 12);
}
public static void test(B b, String name, int age) {
b.eat(name, age);
}
}
3.4无参有返回值
接口 接口对象 = ()-> {表达式;}
package com.qf.day26;
//无参有返回值 接口 接口对象 = ()-> {表达式;}
interface C {
int num();
}
public class Demo9 {
public static void main(String[] args) {
//匿名内部类写法
teat(new C() {
@Override
public int num() {
return 10;
}
});
//Lambda写法
teat(() -> {
return 20;
});
}
public static void teat(C c) {
System.out.println(c.num());
}
}
3.5有参有返回值
接口 接口对象 = (parameter(参数))-> {表达式;}
package com.qf.day26;
//有参有返回值 接口 接口对象 = (parameter(参数))-> {表达式;}
interface D {
int add(int a, int b);//有返回值指的是抽象方法是有返回值的
}
public class Demo10 {
public static void main(String[] args) {
//->前面是 啥? 是方法 带小括号的 方法的名字可以省略
//->后面是 啥? 抽象方法的方法体实现的代码
test((a, b) -> a + b, 4, 5);
}
public static void test(D d, int a, int b) {
int sum = d.add(a, b);
System.out.println(sum);
}
}
4.Stream流
基于Lambda之后,JDK8又引入了一个关于集合类库目前的弊端的解决方案。叫Stream流
现在有个需求:
将List集合 姓张的过滤到另一个新的集合中
package com.qf.day27;
//将List集合 姓张的过滤到另一个新的集合中
import java.util.ArrayList;
import java.util.List;
public class Demo3 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("老邢");
list.add("张得帅");
list.add("张飞");
list.add("张开放");
list.add("蔡徐坤");
List<String> list1 = new ArrayList<>();
//遍历list集合
for (String s : list) {
if (s.startsWith("张")){
//赋值到list1集合中
list1.add(s);
}
}
System.out.println(list1);
//把三个字的名字放到集合中
List<String> list2 = new ArrayList<>();
for (String s : list) {
if (s.length() == 3){
list2.add(s);
}
}
System.out.println(list2);
}
}
用Stream流写的代码
package com.qf.day27;
import java.util.ArrayList;
import java.util.List;
//使用Stream流把一个集合内的姓张的放到另一个集合中
public class Demo4 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("老邢");
list.add("张得帅");
list.add("张飞");
list.add("张开放");
list.add("蔡徐坤");
list.stream().
filter((name)->name.startsWith("张")).
filter((name)->name.length() == 3).
forEach((s)-> System.out.println(s));
}
}
Stream使得代码更加的简洁
4.1获取Stream对象
可以根据集合获取流对象
Collection集合:
default Stream stream(); 返回的是一个有顺序的和集合源数据相关的对象。
就是将集合中的数据变成了另外一种形式而已(流的形式)
1.根据list集合获取流对象
ArrayList<String> list1 = new ArrayList<>(); list1.add("老邢"); list1.add("张得帅"); list1.add("张飞"); list1.add("张开放"); list1.add("蔡徐坤"); list1.stream(). forEach((s)-> System.out.println(s));
2.根据Set集合获取流对象
Set<String> set = new HashSet<>(); set.add("一"); set.add("二"); set.add("三"); set.add("四"); Stream<String> stream = set.stream(); System.out.println(stream);//表示的是地址值
3.根据map集合获取流对象
//map集合 Map<String , String> map = new HashMap<>(); map.put("1" , "红烧鲤鱼"); map.put("2" , "红烧肘子"); map.put("3" , "糖醋排骨"); map.put("4" , "可乐鸡翅"); //map集合没有stream方法,转为集合再来操作 //转为set集合 Set<String> strings = map.keySet(); Stream<String> stream1 = strings.stream(); stream1.forEach((s -> System.out.println(s))); Collection<String> values = map.values(); Stream<String> stream2 = values.stream(); stream2.forEach((s -> System.out.println(s))); //entrySet Set<Map.Entry<String, String>> entries = map.entrySet(); Stream<Map.Entry<String, String>> stream3 = entries.stream(); stream3.forEach((s -> System.out.println(s)));
4.数组
String[] arr = {"a", "b"}; Stream<Object> stream = Stream.of(arr); stream.forEach((s)-> System.out.println(s));
输出结果: 1 2 3 4 红烧鲤鱼 红烧肘子 糖醋排骨 可乐鸡翅 1=红烧鲤鱼 2=红烧肘子 3=糖醋排骨 4=可乐鸡翅 a b
4.2Stream流对象下面的方法
方法就是一个功能
方法的名字 | 方法的作用 | 方法的种类 | 是否支持链式操作 |
---|---|---|---|
count | 统计个数 | 终结方法 | 否 |
forEach | 遍历数据 | 终结方法 | 否 |
filter | 过滤数据 | 可以拼接 | 是 |
limit | 取前几个数据 | 可以拼接 | 是 |
skip | 跳过前几个 | 可以拼接 | 是 |
map | 映射方法 | 可以拼接 | 是 |
concat | 拼接 | 可以拼接 | 是 |
4.2.1count和forEach
count :统计流中的个数,返回值是long类型的数据
forEach: 遍历流中数据的
package com.qf.a_stream;
import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class Demo3 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("刘亦菲");
strings.add("蔡徐坤");
strings.add("成龙");
Stream<String> stream = strings.stream();
long count = stream.count();
System.out.println(count);
//链式操作
long count1 = strings.stream().count();
System.out.println(count1);
//froEach
//对此流的每个元素执行操作
strings.stream().forEach(new Consumer<String>() {
@Override
//将流中的数据 赋值 s
public void accept(String s) {
System.out.println(s);
}
});
strings.stream().forEach((s)-> System.out.println(s));
}
}
4.2.2filter方法
Stream<T> filter(Predicate<? super T> predicate)
返回由与此给定谓词匹配的此流的元素组成的流。
package com.qf.a_stream;
import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class Demo4 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("刘亦菲");
strings.add("蔡徐坤");
strings.add("成龙");
strings.add("杨坤");
strings.add("陈坤");
strings.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
//s流中字符串每个的数据
boolean b = s.endsWith("坤");
return b;
}
}).filter(new Predicate<String>() {
@Override
public boolean test(String s) {
boolean c = s.startsWith("陈");
return c;
}
}).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
strings.stream().filter((goudan)->goudan.endsWith("坤")).filter((s)->s.startsWith("陈")).forEach((s)-> System.out.println(s));
}
}
4.2.3limit方法
限制输出
package com.qf.a_stream;
import java.util.ArrayList;
import java.util.stream.Stream;
public class Demo5 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("刘亦菲");
strings.add("蔡徐坤");
strings.add("成龙");
strings.add("杨坤");
strings.add("陈坤");
strings.add("战三坤");
strings.add("损五坤");
strings.add("爱坤");
//limit 是要前几个数据 根据参数不同
strings.stream().limit(5).forEach((s)-> System.out.println(s));
strings.stream().limit(5).filter((s)->s.endsWith("坤")).forEach((s)-> System.out.println(s));
}
}
4.2.4map方法
处理映射关系的
package com.qf.a_stream;
import java.util.ArrayList;
import java.util.function.Function;
public class Demo6 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("12");
strings.add("13");
strings.add("14");
strings.add("15");
//将字符串数字 转为int类型的数据
// for (String string : strings) {
//
// int i = Integer.parseInt(string);
// System.out.println(i);
// }
strings.stream().map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
int i = Integer.parseInt(s);
return i;
}
}).forEach((Integer s)-> System.out.println(s));
strings.stream().map((s)->Integer.parseInt(s)).forEach((s)-> System.out.println(s));
}
}
4.2.5skip方法
跳过前几个值
package com.qf.a_stream;
import java.util.ArrayList;
public class Demo7 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("12");
strings.add("13");
strings.add("14");
strings.add("15");
strings.stream().skip(2).forEach((s)-> System.out.println(s));
}
}
4.2.6concat合并两个流
package com.qf.a_stream;
import java.util.ArrayList;
import java.util.stream.Stream;
public class Demo8 {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
list1.add("12");
list1.add("13");
list1.add("14");
list1.add("15");
ArrayList<String> strings = new ArrayList<>();
strings.add("刘亦菲");
strings.add("蔡徐坤");
strings.add("成龙");
strings.add("杨坤");
Stream<String> stream = list1.stream();
Stream<String> stream1 = strings.stream();
//将两个流合并
Stream<String> concat = Stream.concat(stream, stream1);
concat.forEach((s)-> System.out.println(s));
}
}
4.3收集流
stream.collect(Collectors.toList())
stream.collect(Collectors.toSet())
toList(); 将流转为List集合
toSet(); 将流转为Set集合
因为真实的开发的时候,最终的结果还是集合 流只是扮演了中间处理数据的角色
package com.qf.a_stream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class Demo9 {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("刘亦菲");
strings.add("蔡徐坤");
strings.add("成龙");
strings.add("杨坤");
strings.add("陈坤");
strings.add("战三坤");
strings.add("损五坤");
strings.add("爱坤");
strings.add("爱坤");
//collect 收集的方法
//stream.collect(Collectors.toList()) 以什么样的方式收集
List<String> list = strings.stream().filter((s) -> s.endsWith("坤")).skip(2).collect(Collectors.toList());
System.out.println(list);
Set<String> set = strings.stream().filter((s) -> s.endsWith("坤")).skip(2).collect(Collectors.toSet());
System.out.println(set);
}
}