1.反射
1.1获取Class对象
-
获取Class对象的三种方式
Class.forName(“包名+ 类名”); 类.class 对象.getClass() package com.qfedu.b_class; import com.qfedu.a_reflect.Person; public class Demo1 { public static void main(String[] args) throws ClassNotFoundException { //类权限定名 Class<?> aClass = Class.forName("com.qfedu.a_reflect.Person"); System.out.println(aClass); //获取所有的信息 Class<Person> personClass = Person.class; System.out.println(personClass); //通过对象调getClass获得 Class<? extends Person> aClass1 = new Person().getClass(); System.out.println(aClass1); } }
1.2获取Constructor对象
1.class对象.getConstructor();
2.construct对象.newInstance();根据构造方法实例化对象
package com.qfedu.c_conStructor;
import com.qfedu.a_reflect.Person;
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对象
Class<Person> personClass = Person.class;
//通过getConstructors()获取对象的所有公开的构造方法
Constructor<?>[] constructors = personClass.getConstructors();
System.out.println(constructors);
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("==============");
//获取一个类所有的构造方法对象
Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
//获取单个constructor对象
//获取无参的构造方法
Constructor<Person> constructor = personClass.getConstructor(null);
System.out.println(constructor);
System.out.println("-----------");
//获取有参构造的构造方法
Constructor<Person> constructor1 = personClass.getConstructor(String.class);
System.out.println(constructor1);
Constructor<Person> constructor2 = personClass.getConstructor(int.class);
System.out.println(constructor2);
//newInstance(Object...parameter) 是constructor对象调的
//获取无参构造方法的内容,赋默认的值null
Person person = constructor.newInstance(null);
System.out.println(person);
//如果是有参的内容,先对属性进行赋值
Person person1 = constructor1.newInstance("狗蛋");
System.out.println(person1);
}
}
1.3获取Method对象
1.class对象.getMethod(String name, Class<?> …parameterType);
2.method对象.invoke(Object obj, Object… initargs);
package com.qfedu.d_method;
import com.qfedu.a_reflect.Person;
import java.lang.reflect.Method;
public class Demo1 {
public static void main(String[] args) throws NoSuchMethodException {
Class<Person> personClass = Person.class;
//通过class对象获取一个类下面成员方法对象Method
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);
}
//获取单个成员方法,无法获取私有的成员方法
Method eat = personClass.getMethod("eat", null);
System.out.println(eat);
}
}
1.4获取Field对象
1.getFields获取公开的属性
2.getDeclaredField();获取单个属性
3.set(对象,要被赋的值) 对对象属性进行赋值
4.setAccessible(boolean);暴力反射,可以是对象接近私有化属性
package com.qfedu.e_field;
import com.qfedu.a_reflect.Person;
import java.lang.reflect.Field;
public class Demo1 {
public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
//属性是在一个类下,也要Class对象获取属性
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);
}
//获取单个属性,获取私有的和默认的会报错
Field sex = personClass.getField("sex");
System.out.println(sex);
//获取单个属性,都可以获取
Field name = personClass.getDeclaredField("name");
System.out.println(name);
//对属性进行赋值
Person person = personClass.newInstance();
sex.set(person,'蛋');
System.out.println(person);
//通过暴力反射使对象接近私有属性,从而可以对私有属性进行赋值
name.setAccessible(true);
name.set(person,"狗蛋");
System.out.println(person);
}
}
1.5反射的优缺点
优点 :可以让代码更加灵活、为各种框架提供开箱即用的功能提供了便利
缺点 :让我们在运行时有了分析操作类的能力,这同样也增加了安全问题。
比如可以无视泛型参数的安全检查(泛型参数的安全检查发生在编译时)。
另外,反射的性能也要稍差点,不过,对于框架来说实际是影响不大的
2.jdk1.8新特性
2.1单例模式
只允许使用一个对象
固定的语法格式
懒汉式的写法
private static Dog dog = null;
private Dog(){
}
public static synchronized Dog getInstance(){
if (dog == null) {
dog = new Dog();
}
return dog;
}
饿汉式的写法
package com.qfedu.f_jdk;
class Cat {
//限制了对象唯一性以及线程唯一性
private static final Cat cat = new Cat();
private Cat() {
}
public static Cat getInstance() {
return cat;
}
}
public class Demo4 {
public static void main(String[] args) {
//获取Cat对象
//获得的对象是同一个,根据地址可知
Cat cat = Cat.getInstance();
System.out.println(cat);//com.qfedu.f_jdk.Cat@1b6d3586
Cat cat1 = Cat.getInstance();
System.out.println(cat1);//com.qfedu.f_jdk.Cat@1b6d3586
}
}
注意:懒汉式是线程安全的
饿汉式是线程不安全的
开发中使用懒汉式,因为性能比较好,节约内存
2.2序列化
类 ObjectInputStream(反序列化) 和 ObjectOutputStream(序列化) 是高层次的数据流,它们包含反序列化和序列化对象的方法。
功能:将对象的属性,方法序列化存入文件中,后缀是ser.(乱码,无法查看)序列化
并从文件中读取出这个文件。 反序列化
2.2.1案例
正序列化,将对象属性和方法存入的文件中
package com.qfedu.g_test;
import java.io.*;
class Person implements Serializable{
String name;
int age;
char sex;
public void sleep(){
System.out.println("我喜欢睡懒觉");
}
}
public class Demo1 {
public static void main(String[] args) throws IOException {
//获取属性序列化存入的文件地址
FileOutputStream fos = new FileOutputStream(new File("D:/aaa/732.ser"));
//将文件地址传入到反序列化流中
ObjectOutputStream oos = new ObjectOutputStream(fos);
//对对象内容进行赋值
Person person = new Person();
person.age = 22;
person.name = "彩云";
person.sex = '公';
//将对象内容序列化到文件中
oos.writeObject(person);
System.out.println("存入成功");
//关闭流
oos.close();
fos.close();
}
}
反序列化,在文件中读取对象的属性和方法
package com.qfedu.g_test;
import java.io.*;
public class Demo2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//获取要读取内容的地址
FileInputStream fis = new FileInputStream(new File("D:/aaa/732.ser"));
//将内容引入到系列化输出流中
ObjectInputStream ois = new ObjectInputStream(fis);
//进行强转,获取Person对象
Person o = (Person)ois.readObject();
//读取文件中的内容
System.out.println(o.name);
System.out.println(o.age);
System.out.println(o.sex);
o.sleep();
//关闭流
ois.close();
fis.close();
}
}
2.3Lambda表达式
Lambda表达式运行函数式编程。就是简化代码的。变得更加简洁,但是可读性特别差
1.Lambda表达式可以用来简化匿名内部类的书写
2.Lambda表达式只能简化函数式接口的匿名内部类的写法
3.函数式接口只有一个抽象方法
package com.qfedu.h_lambda;
import java.util.Arrays;
import java.util.Comparator;
public class Demo1 {
public static void main(String[] args) {
Integer[] arr= {6,2,4,9,3,1,10};
//lambda简化匿名内部类
Arrays.sort(arr, (Integer o1, Integer o2) -> {
return o1 - o2;
}
);
//对lambda简化
//一行代码搞定
Arrays.sort(arr,((o1, o2) -> o1 - o2));
//已经拍好序
//正常匿名内部类写法
// Arrays.sort(arr, new Comparator<Integer>() {
// @Override
// public int compare(Integer o1, Integer o2) {
//
// return o1 - o2;
// }
// });
System.out.println(Arrays.toString(arr));//[1, 2, 3, 4, 6, 9, 10]
}
}
1.参数类型可以省略不写
2.如果只有一个参数,参数类型可以省略,同时()也可以省略。
3.如果Lambda表达式只有一行,大括号,分号,return可以省略不写,但需要进行同时省略
package com.qfedu.h_lambda;
public class Demo2 {
public static void main(String[] args) {
//传统写法
// lambda(new Swim() {
// @Override
// public void swimming() {
// System.out.println("正在游泳~~~~");
// }
// });
//简化写法
// lambda(()-> {
// System.out.println("正在游泳~~~");
// }
// );
//对lambda写法简化
//参数类型可以省略不写
//如果只有一个参数,参数类型可以省略,同时()也可以省略。
//如果Lambda表达式只有一行,大括号,分号,return可以省略不写,但需要进行同时省略
lambda(() -> System.out.println("正在游泳"));
}
public static void lambda(Swim swim){
swim.swimming();
}
}
interface Swim{
void swimming();
package com.qfedu.h_lambda;
import java.util.Arrays;
import java.util.Comparator;
public class Demo3 {
public static void main(String[] args) {
String[] arr = {"aaa", "aaaa", "aa", "a","aaaaa"};
//匿名内部类写法
// Arrays.sort(arr, new Comparator<String>() {
// @Override
// public int compare(String o1, String o2) {
// return o1.length() - o2.length();
// }
// });
//lambda写法
// Arrays.sort(arr,(String o1, String o2) ->{
// return o1.length() - o2.length();
// }
// );
//lambda简化写法
Arrays.sort(arr,( o1, o2) ->
o1.length() - o2.length()
);
System.out.println(Arrays.toString(arr));//[a, aa, aaa, aaaa, aaaaa]
}
}
2.3.1语法格式
接口 接口对象 = ()->表达式; 无参 无返回值的
接口 接口对象 = (parameter)->表达式; 有参 无返回值的
接口 接口对象 = ()->{表达式;}; 无参 有返回值的
接口 接口对象 = (parameter)->{表达式;}; 有参有返回值