反射

Java基础知识框架

什么是类对象?

  • 类的对象:基于某个类new出来的对象,也称为实例对象。
  • 类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)
public class TestClassObject {
	public static void main(String[] args) {
		//伪代码
//		Class c = new Class();
//		c.packageName = "com.qf.day34.reflects.Student";
//		c.className = "Student";
//		c.superClass = "java.lang.Object";
//		C.fileds = new Filed[] {"String name","int age","String sex"};
//		c.methods = new methods[] {"public void study() {}","public void exam() {}","public void work() {}"};
//		c.constructors() = new constructors[] {"(){}","(String name){}"};
		Student s =  new Student();//类的对象,基于模板生成的
		System.out.println(s.getClass().toString());
		Class c = s.getClass();//类对象,类的对象的模板
		c.toString();
	}
}
class Student{
	String name;
	int age;
	String sex;
	public Student() {}
	public Student(String name) {
	}
	
	public Student(int age) {}
	public void study() {}
	public void exam() {}
	public void work() {}
}

模板类Class(类似于做月饼的模具,对象是类的实例,类是对象的模板)

获取类对象的方法

  • 通过类的对象,获取类对象
    Student s = new Student();
    Class c = s.getClass();
  • 通过类名获取类对象
    Class c = 类名.class
  • 通过静态方法获取类对象
    Class c = Class.forName(“包名.类名”);
public class TestGetClassObject {
	public static void main(String[] args) throws ClassNotFoundException {
		
		//1.通过类的对象,获取Class对象
		Person p = new Person();//类的对象
		Class c = p.getClass();//类对象Class对象,保存了Person.class这个文件中类的所有信息
		System.out.println(c.getName());
		
		//2.通过类名获取Class对象
		Class c2 =  Person.class;//但先有Person再有.class
		System.out.println(c2.getName());
		
		//3.通过Class的静态方法获得Class对象
		Class c3 = Class.forName("com.qf.day34.reflects.Person");// throws ClassNotFoundException
		System.out.println(c3.getName());
	}
	//该方法返回一个类对象(Class对象)
	//第一种方式,传不同类时,需要改Person,频繁修改。改为Object
//	public static Class getClassObject(Person p) {
//		Class c = p.getClass();
//		return c;
//	}
	//
	public static Class getClassObject(String className) {	
		Class c = null;
		try {
			c = Class.forName(className);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}	
		return c;
	}
	
}
class Person{
	
}

常见操作

常见方法:

  • public String getName()
  • public Package getPackage()
  • public Class<? super T>getSuperclass()
  • public Class<?>[] getInterfaces()
  • public Filed[] getFields
  • public Methods[] getMethods()
  • public Constructor<?>[] getConstructors()
  • public T newInstance()
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestClassMethods {
	public static void main(String[] args) throws Exception {
		//1.获取类对象
		Class c = Class.forName("com.qf.day34.methods.Student");
		System.out.println(c.getName());
		//获取指定类型的包
		Package  pack = c.getPackage();
		System.out.println(pack.getName());
		
		//获得父类的Class对象
		Class superClass = c.getSuperclass();
		System.out.println(superClass.getName());
		
		//获得接口的Class对象
		Class[] interfaces = c.getInterfaces();
		for(Class inter:interfaces) {
			System.out.println(inter.getName());
		}
		
		//获取属性(public)自身+父类的公开属性
		Field[] fields = c.getFields();
		for(Field f : fields) {
			System.out.println(f.getName());	
		}
		
		System.out.println("---------------------");
		//获得Class对象的自身所在属性
		Field[] fields2 = c.getDeclaredFields();
		for(Field f : fields2) {
			System.out.println(f.getName());	
		}
		
		System.out.println("--------Method-------------");
		//获取方法(自身+父类的所有公开方法)
		Method[] methods = c.getMethods();
		for(Method m : methods) {
			System.out.println(m.getName());	
		}
		
		System.out.println("--------Methodshelf-------------");
		//获取方法(自身+父类的所有公开方法)
		Method[] methods2 = c.getDeclaredMethods();
		for(Method m : methods2) {
			System.out.println(m.getName()+":"+m.getReturnType());	
		}
		
		System.out.println("--------constructor-------------");
		Constructor[] cs = c.getConstructors();
		for(Constructor ct : cs) {
			System.out.print(ct.getName()+":");
			Class[] parm = ct.getParameterTypes();//获取构造方法的形参
			for(Class p : parm) {
				System.out.println(p.getName());
			}
		}
		System.out.println("---------------------");
		Object o = c.newInstance();
		Student stu = (Student)o;
		System.out.println(stu);
	}
}
class Person{
	public String sex;
	public double money;
	public void eat() {}
	public void sleep() {}
}
class Student extends Person implements Serializable,Runnable,Comparable{
	public String name;
	public int age;
	double score;
	
	public Student() {}
	public Student(String name) {
	}
	public Student(String name,int age) {}
	private int aaa() {
		return 0;
	}
	public Student(int age) {}
	public void study() {}
	public void exam() {}
	public void work() {}
	
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}
}

在这里插入图片描述

public class TestNewInstance {
	public static void main(String[] args) throws Exception {
//		//1.手工new对象
//		Teacher t = new Teacher();
//		t.name = "aaa";
//		System.out.println(t.name);
		
		//2.反射通过类对象创建类的对象
//		Class c = Teacher.class;
//		Teacher t = (Teacher)c.newInstance();
//		t.name = "bbb";
//		System.out.println(t.name);
		
		Object o = createObject("com.qf.day34.methods.Teacher");
		System.out.println(o);
	}
	//不直接返回Teacher ,为普适性
	//创建对象:
	//工厂,创建对象工厂
	public static Object createObject(String className) {
		try {
			Class c = Class.forName(className);
			return c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

class Teacher{
	String name;
	String sex;
	Integer age;
	public Teacher() {
		
	}
	public Teacher(String name, String sex, Integer age) {
		super();
		this.name = name;
		this.sex = sex;
		this.age = age;
	}
	
	public void study() {
		System.out.println("我在学习");
	}
	public void exam() {
		System.out.println("我在考试");
	}
	public void calc() {
		System.out.println("我在计算");
	}
	
}

TestNewInstanceForFiles,案例前需要Files\application.txt创建并添加信息

import java.io.BufferedReader;
import java.io.FileReader;

public class TestNewInstanceForFiles {
	public static void main(String[] args) throws Exception {
		FileReader fr = new FileReader("Files\\application.txt");
		BufferedReader br = new BufferedReader(fr);
		String className = br.readLine();
		Object o = createObject(className);
		System.out.println(o);
	}
	//创建对象:
	//工厂,创建对象工厂
	public static Object createObject(String className) {
		try {
			Class c = Class.forName(className);
			return c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}
class Dog{
	
}

工厂设计模式

  • 开发中有一个非常重要的原则“开闭原则”,对拓展开放、对修改关闭
  • 工厂模式主要负责对象创建的问题
  • 可通过反射进行工厂模式的设计,完成动态的对象创建

invoke方法,执行某个实例

import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Method;

public class TestInvokeMethod {

	public static void main(String[] args)throws Exception{
		FileReader fr = new FileReader("Files\\application.txt");
		BufferedReader br = new BufferedReader(fr);
		String className = br.readLine();
		
		Object o = createObject(className);
		Class c = o.getClass();//类对象
		Method m = c.getMethod("study", null);
		m.invoke(o, null);//通过invoke方法,执行某个实例方法,参数:Object->所需对象,args->调用的方法所需的实参
	    
		
		Method m2 = c.getMethod("study",int.class);
		m2.invoke(o, 111); //接收方法返回值,如果是基本类型,则转换为包装
		
		Method m3 = c.getMethod("exam",int.class,double.class,String.class);
		m3.invoke(o,2,90,"kunyan");
		
//		Method m4 = c.getMethod("clac", null);error无法获取私有方法
		Method m4 = c.getDeclaredMethod("clac", null);//获得自身方法,包含私有
		
		//注意:反射是一种Java底层技术,可以取消语言检查,突破封装
		m4.setAccessible(true);
		m4.invoke(o, null);
	}
	
	//工厂--->创建对象的
	public static Object createObject(String className) {
		try {
			Class c = Class.forName(className);
			return c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	

}
class Student{
	String name;
	Integer age;
	String sex;
	Double score;
	public Student() {}
	public Student(String name, Integer age, String sex, Double score) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.score = score;
	}

	public Student(int age) {}
	
	public void study() {
		System.out.println("正在学习。。。。");
	}
	public int study(int a) {
		System.out.println("学习"+a+"小时");
		return 0;
	}
	public void exam(int a, double b ,String s) {
		System.out.println(s+"学习了"+a+"小时"+"考了"+b);
	}
	
	private void clac() {
		System.out.println("计算。。。");
	}
}

通用方式:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Method;

public class TestInvokeAnything {
	public static void main(String[] args) throws Exception {	
		//invokeAny() --->执行方法
		//对象(Object)、方法名称(String)、形参(Class)、实参(Object)
//		FileReader fr = new FileReader("Files\\application.txt");
//		BufferedReader br = new BufferedReader(fr);
//		String className = br.readLine();
		Object o = createObject("com.qf.day35.reflects.Student");
		
		invokeAny(o,"exam",new Class[] {int.class,double.class,String.class},1,99,"kunyan");
		invokeAny(o,"study",null,null);
		invokeAny(o,"study",new Class[] {int.class},100);
		
	}
	//通用(调用任何一个方法)
	public static void invokeAny(Object obj ,String methodName,Class[] types,Object... args)throws Exception {
		//使用反射技术执行任何方法
		//类对象
		Class c = obj.getClass();
		//获得方法的对象Methods
		Method m = c.getDeclaredMethod(methodName, types);
		
		//执行方法
		m.invoke(obj, args);
	}
	
	//工厂--->创建对象的
	public static Object createObject(String className) {
		try {
			Class c = Class.forName(className);
			return c.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
}

单例设计模式

  • 只允许创建一个该类的对象
```java
package com.qf.day35.singletons;

public class Test {
	public static void main(String[] args) {
		Student stu  = Student.getStudent();
		Student stu1  = Student.getStudent();
		Student stu2  = Student.getStudent();
		System.out.println(stu);
		System.out.println(stu1);
		System.out.println(stu2);
	}
}
//只创建了一次对象,一个对象----->只能在一个引用中
class Student{
	static int count = 0;
	//构造方法私有化
	private Student() {}
	
	public static Student getStudent() {
		count++;
		if(count>1) {
			return null;
		}else {
			return new Student();
		}
	}
	
}


 - 方式1:饿汉式[类加载时创建,天生线程安全]
 - 方式2:懒汉式[使用时创建,线程不安全,加同步]
 - 方式3:懒汉式(使用时创建,线程安全)

```java
package com.qf.day35.singletons;

public class TestSingleton {
	public static void main(String[] args) {
		Singleton s1 =Singleton.getInstance();
//		Singleton s2 =Singleton.getInstance();
//		Singleton s3 =Singleton.getInstance();
	
//		Singleton.instance=null;加私有,依然不可靠,可以利用setAccessible突破封装,所以加final
		System.out.println(s1);
//		System.out.println(s2);
//		System.out.println(s3);

		//什么时候创建的?类加载就创建,如果没有使用的话则浪费空间
		//线程安全吗?天生线程安全,无锁
		
		

		Singleton1 s11 =Singleton1.getInstance();
//		Singleton1 s12 =Singleton1.getInstance();
//		Singleton1 s13 =Singleton1.getInstance();
		System.out.println(s11);
//		System.out.println(s12);
//		System.out.println(s13);
		
		//调用时创建的
		//线程不安全,容易创建不同对象,上锁后安全,但效率低
		
		
		Singleton2 s23 =Singleton2.getInstance();
		System.out.println(s23);
	}
}
//饿汉式:天生线程安全,无锁。类加载时创建,但是不用的时候也被创建了,占用资源
class Singleton{
	private static final Singleton instance = new Singleton();
	private Singleton() {}
	
	public static Singleton getInstance() {
		return instance;
	}
}
//懒汉式:使用时创建、天生线程不安全(加同步锁)
class Singleton1{
	private static Singleton1 instance = null;
	private Singleton1(){}
	public synchronized static Singleton1 getInstance() {
		if(instance == null) {
			instance = new Singleton1();
		}
		return instance;
	}
}

//懒汉式:使用时创建、天生线程安全
class Singleton2{
	private Singleton2() {}
	private static class Holder{
		static final Singleton2 instance = new Singleton2();
	}
	public  static Singleton2 getInstance() {
		return Holder.instance;
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章