线程的第三种创建方式
package com.qfedu.test1;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.FutureTask;//1.创建Callable接口的实现类 <v>泛型 控制重写方法的返回值类型class MyThread implements Callable<String>{//2.重写call方法@Overridepublic String call() throws Exception {// TODO Auto-generated method stubSystem.out.println(Thread.currentThread().getName() + "实现callable");return "返回值";}}public class Demo1 {public static void main(String[] args) throws InterruptedException, ExecutionException {//3.实例化Callable的实现类MyThreadMyThread myThread = new MyThread();//4.将对象给FutureTask去执行//线程池知识 后面会讲//FutureTask实现了Future,Runnable接口FutureTask<String> task = new FutureTask<String>(myThread);//所以在开启一个任务 aaaaaa接下面注释FutureTask<String> task1 = new FutureTask<String>(myThread);Thread thread = new Thread(task,"线程1");Thread thread1 = new Thread(task1,"线程2");//开启的两个线程,却只打印了一个,因为结果被缓存了//异步任务,等待、运行、完成这几个状态。当一个线程处理的是同一个任务的时候task//自动返回完成状态,下面线程在执行的时候,会把它当成已经完的任务,所以不在执行//所以在开启一个任务 aaaaaathread.start();thread1.start();System.out.println(task.get());}}
一、反射
平时获取对象,new一个对象。现在反着来,通过反射获取对象。
入门案例
1.Person
package com.qfedu.test2fanshe;public class Person {String name;int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}}
2.Demo1
package com.qfedu.test2fanshe;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;//反射public class Demo1 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {//正常方式获取对象Person person = new Person();person.name = "a a";System.out.println(person.name);//反射入门案例//Person.class 看成一个对象Class<?> aClass = Class.forName("com.qfedu.test2fanshe.Person");// Class<?> aClass = Person.class;//获取无参构造 Constructor(构造方法)是Person类下面的无参构造对象Constructor<?> constructor = aClass.getConstructor(null);Constructor<?> constructor1 = aClass.getConstructor(String.class,int.class);//实例化 Instance(实例)Person person1 = (Person)constructor.newInstance(null);Person person2 = (Person)constructor1.newInstance("博儿",23);person1.name = "奥斯卡";person1.age = 16;System.out.println(person1);System.out.println(person2);/** 1.获取Class对象(类的字节码文件) Person.class里面有构造方法,属性,方法* 2.通过Class对象获取Constructor(构造方法)对象* 3.通过构造方法对象创建对象*/}}
1.获取class对象
为什么要获取class对象?相当于获取.class文件对象,通过它可以获取这个类下面的属性、构造方法、方法等信息
三种方式:
package com.qfedu.test2fanshe;public class Demo2 {public static void main(String[] args) throws Exception {//有三种获取class对象的方式//1.第一种:方法名是forname 参数是字符串的包名+类名Class<?> aClass = Class.forName("com.qfedu.test2fanshe.Person");System.out.println(aClass);//2.第二种:Class<Person> personClass = Person.class;System.out.println(personClass);//3.第三种:Class<? extends Person> aClass2 = new Person().getClass();System.out.println(aClass2);}}
2.获取Constructor类对象
2.1获取构造方法的四个方法
Demo3
getConstructors() 方法名 获取当前类下面的所有非私有化的构造方法对象
getDeclaredConstructors() 方法名 获取当前类下面的所有构造方法对象
getConstructor() 方法名 通过参数的不同,来获取所对应的非私有的构造方法
getDeclaredConstructor() 方法名 这个可以获得私有的构造方法,加Declared都是可以获得私有的
package com.qfedu.test2fanshe;import java.lang.reflect.Constructor;public class Demo3 {public static void main(String[] args) throws Exception {Class<?> aClass = Class.forName("com.qfedu.test2fanshe.Person");//getConstructors() 方法名//获取当前类下面的所有非私有化的构造方法对象(获取public修饰的构造方法)Constructor<?>[] constructors = aClass.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println(constructor);}System.out.println("-------------------------");//获取当前类下面的所有构造方法对象//getDeclaredConstructors() 方法名Constructor<?>[] constructors1 = aClass.getDeclaredConstructors();for (Constructor<?> constructor : constructors1) {System.out.println(constructor);}System.out.println("-------------------------");//通过参数的不同,来获取所对应的非私有的构造方法//getConstructor()方法名 ()里啥也不写或者null 获取无参构造Constructor<?> constructors2 = aClass.getConstructor();System.out.println(constructors2);//无参构造Constructor<?> constructors3 = aClass.getConstructor(String.class,int.class);System.out.println(constructors3);//带有String和int的有参构造System.out.println("-------------------------");//这个可以获得私有的构造方法,加Declared都是可以获得私有的Constructor<?> constructors4 = aClass.getDeclaredConstructor(int.class);System.out.println(constructors4);}}
2.2创建对象是通过构造方法创建的
//newInstance这个方法是调用Contructor对象调用的Person person = (Person)constructors2.newInstance();System.out.println(person);Person person1 = (Person)constructors3.newInstance("博儿",18);System.out.println(person1);
3.获取Method类对象
Method[] getMethods() public修饰的方法以及父类继承过来的Object下的方法
Method[] getDeclaredMethods() 获取自己下面的所有方法(不含父类),无论什么修饰的
Method getMethod(“方法名”,方法参数数据类型),获取指定public一个方法,无参的写null
Method getDeclaredMethod(“wc”, null) 获取一个方法 可以获取私有的
Object invoke(Obj obj, Obj… args);【重点】Method对象的方法
package com.qfedu.test2fanshe;import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class Demo4 {public static void main(String[] args) throws Exception {Class<?> aClass = Class.forName("com.qfedu.test2fanshe.Person");//public修饰的方法以及父类继承过来的Object下的方法 都打印出来//getMethods()Method[] methods = aClass.getMethods();for (Method method : methods) {System.out.println(method);}System.out.println("************************");//获取自己下面的所有方法(不含父类),无论什么修饰的//getDeclaredMethods()Method[] methods1 = aClass.getDeclaredMethods();for (Method method : methods1) {System.out.println(method);}System.out.println("************************");//获取一个方法 getMethod("方法名",方法参数数据类型),无参的写nullMethod method = aClass.getMethod("eat", null);System.out.println(method);Method method1 = aClass.getMethod("play", String.class);System.out.println(method1);System.out.println("************************");//Object invoke(Obj obj, Obj... args);【重点】Method对象的方法//第一个参数 这个方法在那个对象下面//第二个参数 方法的实参Constructor<?> constructor = aClass.getConstructor(null);Object obj = constructor.newInstance(null);method.invoke(obj, null);method1.invoke(obj, "游戏");}}
4.获取Field类对象【类下面的属性】
Field[] getFields() 获取所有public修饰的属性
Field[] getDeclaredFields() 获取所有的属性
Field getField(“属性名字”) 获取指定public修饰的属性
Field getDeclaredField(“属性名字”) 获取指定的属性(任何修饰符都可以)
set(Object o,Object Value)拿属性对象调用的,对属性进行赋值
package com.qfedu.test2fanshe;import java.lang.reflect.Constructor;import java.lang.reflect.Field;//public class Demo5 {public static void main(String[] args) throws Exception {Class<?> aClass = Class.forName("com.qfedu.test2fanshe.Person");//获取类对象下的的属性reflect包下的Filed//getFields() 获取所有public修饰的属性Field[] fields = aClass.getFields();for (Field field : fields) {System.out.println(field);}System.out.println("*****************");//Field[] getDeclaredFields() 获取所有的属性Field[] fields1 = aClass.getDeclaredFields();for (Field field : fields1) {System.out.println(field);}System.out.println("*****************");//Field getField("属性名字") 获取指定public修饰的属性Field field = aClass.getField("sex");System.out.println(field);System.out.println("*****************");//getDeclaredField("属性名字") 获取指定的属性(任何修饰符都可以)Field field1 = aClass.getDeclaredField("weight");System.out.println(field1);//属性对象获取出来,可以进行赋值//set(Object o,Object Value)拿属性对象调用的,对属性进行赋值//第一个参数 属性在那个对象下面//第二个参数 属性的值Constructor<?> constructor = aClass.getConstructor(null);Person person = (Person)constructor.newInstance(null);field.set(person, '男');field1.setAccessible(true);//暴力反射field1.set(person, 80.8);//私有的不能直接赋值 加上上一行的暴力反射System.out.println(person);}}
二、单例模式
模式涉及的目的是为了让代码更加简洁,效率更低,修改起来更方便
要求程序运行过程中,只保证有且只有一个对象
问题:通过构造方法和new创建的时候,都是不同的对象
现在不能一直new。只能写一个new,然后公共不用在new
不够安全,需要加锁
package com.qfedu.test3danlimoshi;//单例模式class Single{String name;//static修饰 早于对象的创建//静态方法种不能使用非静态的成员属性private static Single single = null;//私有化的构造方法的目的。为了不让在这个类外面使用new关键字private Single() {}//用方法实力对象public static Single getInstance() {//来判断single是否是第一个new的synchronized (Single.class) {if (single == null) {single = new Single();}}return single;}}//弄俩线程 验证安全问题class MyThread1 implements Runnable{@Overridepublic void run() {Single single = Single.getInstance();System.out.println(single);}}class MyThread2 implements Runnable{@Overridepublic void run() {Single single = Single.getInstance();System.out.println(single);}}public class Demo1 {public static void main(String[] args) {//两个内存地址一样 说明是同一个对象// Single single = Single.getInstance();// System.out.println(single);// Single single1 = Single.getInstance();// System.out.println(single1);new Thread(new MyThread1()).start();new Thread(new MyThread2()).start();}}
三、java序列化(IO流)
3.1序列化对象
目的:将对象写入到文件中
ObjectOutputStream
package com.qfedu.test4xuliehua;import java.io.Serializable;//在employee实现一个Serializable接口 不然在运行时会报错public class Employee implements Serializable{String name;int age;String address;public void printInfo() {System.out.println("姓名为:" + name + ",年龄为:" + age + ",住址为:" + address);}}
package com.qfedu.test4xuliehua;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;//序列化public class Demo1 {public static void main(String[] args) throws IOException {Employee employee = new Employee();employee.name = "朱志伟";employee.age = 24;employee.address = "地球";employee.printInfo();//将employee对象进行序列化FileOutputStream fos = new FileOutputStream(new File("E:/aaa/emp.ser"));ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(employee);//在employee实现一个Serializable接口oos.close();fos.close();}}
3.2反序列化对象
目的:将文件中的数据取出来 给一个对象
package com.qfedu.test4xuliehua;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.ObjectInputStream;import com.qfedu.test4xuliehua.Employee;//反序列化public class Demo2 {public static void main(String[] args) throws IOException, ClassNotFoundException {FileInputStream fis = new FileInputStream(new File("E:/aaa/emp.ser"));ObjectInputStream ois = new ObjectInputStream(fis);Employee employee = (Employee)ois.readObject();System.out.println(employee.name);System.out.println(employee.age);System.out.println(employee.address);employee.printInfo();ois.close();fis.close();}}
总结
序列化是将对象写进文件。反序列化是从文件读取对象
有的时候,数据比较重要,存数据库的话,爬数据丢失。因此可以将序列化到本地磁盘一次备份。使用的时候再从本地反序列化出来。
四、关于框架的知识
通过反射运行配置文件的类型
类1
package com.qfedu.test5;public class Service1 {public void doService1() {System.out.println("业务方法1");}}
类2
package com.qfedu.test5;public class Service2 {public void doService2() {System.out.println("业务方法2");}}
测试1
package com.qfedu.test5;public class Demo1 {public static void main(String[] args) {Service1 service1 = new Service1();service1.doService1();//当需要从第一个业务方法,切换到第二个业务方法//需要重新new 重新调用Service2 service2 = new Service2();service2.doService2();}}
测试2通过反射进行改进
1.首先准备一个配置文件,暂且叫spring.txt 放在项目src路径下面,里面存的是类的名字和方名字
spring.txt
class=reflection.Service1method=doService1
Demo2
package com.qfedu.test5;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.util.Properties;//改进Demo1 通过反射public class Demo2 {public static void main(String[] args) throws Exception {//Spring.txt文件读取内容File file = new File("D:\\eclipse-workspace\\day413\\src\\spring.txt");//Properties 这个类可以读取配置文件中的信息封装到一个对象中Properties properties = new Properties();//将配置信息里的数据封装到Properties这个对象里properties.load(new FileInputStream(file));//获取内容 Spring.txt中 =左边是键 =右边是值String className = (String)properties.get("class");System.out.println(className);String methodName = (String)properties.get("method");System.out.println(methodName);//通过类名获取类对象Class<?> aClass = Class.forName(className);//获取方法对象Method method = aClass.getMethod(methodName, null);//获取构造器对象Constructor<?> constructor = aClass.getConstructor(null);Object object = constructor.newInstance(null);method.invoke(object, null);}}
五、通过反射越过泛型的检查
泛型是在编译期间起作用的,在编译后的.class文件是没有泛型的。本质都是Object类型的数据
package com.qfedu.test6fanshefanxing;import java.lang.reflect.Method;import java.util.ArrayList;public class Demo1 {public static void main(String[] args) throws Exception {ArrayList<String> list = new ArrayList<String>();list.add("啊");list.add("吧");list.add("从");// list.add(5);//报错//通过反射越过泛型//反向获取上面ArrayList对象的Class对象,//反向在调用add方法就可以Class listClass = list.getClass();//new 对象.getClass();//获取add方法 对象 add(Object obj)Method addMethod = listClass.getMethod("add", Object.class);addMethod.invoke(list, 5);//把int数据存到String类型集合里for (Object obj : list) {System.out.println(obj);}}}
