学习Java第三十五天--反射

17.反射

17.1 什么是类对象

  • 类的对象:基于某个类new出来的对象,也称为实例对象;
  • 类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)

在这里插入图片描述

public class TestClassObject {

	public static void main(String[] args) {
		
		Student s = new Student();//类的对象,基于模板生成的
		System.out.println(s.getClass().toString());
		
		Class c = s.getClass();//类对象,是类的对象的模板
		System.out.println(c.toString());
		

	}

}

class Student{
	String name;
	int age;
	String sex;
	public Student() {
		super();
	}
	public Student(String name) {
		super();
		this.name = name;
	}
	public Student(int age) {
		super();
		this.age = age;
	}
	
	public void study() {}
	public void exam() {}
	public void work() {}
}

17.2 获取类对象的方法

  • 通过类的对象,获取类对象;
    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;
		System.out.println(c2.getName());
		
		//3.通过Class的静态方法获取Class对象
		Class c3 = Class.forName("com.qf.Day34.Person");
		System.out.println(c3.getName());
	}
	//该方法返回一个类对象(Class对象)
	public static Class getClassObject(String className) {
		Class c = null;
		try {
			c = Class.forName(className);
		}catch(ClassNotFoundException e) {
			e.printStackTrace();
		}
		return c;
	}
}
class Person{
	
}

输出结果:

com.qf.Day34.Person
com.qf.Day34.Person
com.qf.Day34.Person

17.3 类对象的常用方法

public String getName()
public Package getPackage()
public Class<? super T> getSuperclass()
public Class<?>[] getInterfaces()
public Field[] getFields()
public Method[] 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 ClassNotFoundException, InstantiationException, IllegalAccessException {
		//1.获取类对象
		Class c = Class.forName("com.qf.Day34.Student2");
		System.out.println(c.getName());
		
		System.out.println("---Package---");
		//2.获取指定类对象的包
		Package pack = c.getPackage();
		System.out.println(pack.getName());
		System.out.println();
		
		System.out.println("---Superclass---");
		//3.获取父类的Class对象
		Class superClass = c.getSuperclass();
		System.out.println(superClass.getName());
		System.out.println();
		
		System.out.println("---Interfaces---");
		//4.获得接口的Class对象
		Class[] interfaces = c.getInterfaces();
		for (Class inter : interfaces) {
			System.out.println(inter.getName());
		}
		System.out.println();
		
		System.out.println("---Fields---");
		//获取属性(自身+父类的公开属性)
		Field[] fields = c.getFields();
		for (Field field : fields) {
			System.out.println(field.getName());
		}
		System.out.println();
		
		System.out.println("---Fields---");
		//获取Class对象自身的所有属性(包括私有)
		Field[] fields2 = c.getDeclaredFields();
		for (Field field : fields2) {
			System.out.println(field.getName());
		}
		System.out.println();
		
		System.out.println("---Methods---");
		//获取方法(自身+父类的所有公开方法)
		Method[] methods = c.getMethods();
		for (Method method : methods) {
			System.out.println(method.getName());
		}
		System.out.println();
		
		System.out.println("---Methods---");
		//获取Class对象自身的所有方法(包括私有)
		Method[] method2 = c.getDeclaredMethods();
		for (Method method : method2) {
			System.out.println(method.getName()+":"+method.getReturnType());//方法名和返回值类型	
		}
		System.out.println();
		
		System.out.println("---Constructors---");
		Constructor[] cs = c.getConstructors();
		for (Constructor constructor : cs) {
			System.out.print(constructor.getName()+":");
			Class[] param = constructor.getParameterTypes();//获取构造方法的形参
			for (Class p : param) {
				System.out.println(p.getName());
			}
		}
		
		System.out.println("\n\n");
		Object o  = c.newInstance();
		Student2 stu = (Student2)o;
		System.out.println(o);
		System.out.println(stu);
	}

}
class Person2{
	public String sex;
	public double money;
	public void eat() {}
	public void sleep() {}
}
class Student2 extends Person2 implements Serializable , Runnable , Comparable{
	public String name;
	int age;
	String sex;
	private double score;
	public Student2() {
		super();
	}
	public Student2(String name) {
		super();
		this.name = name;
	}
	public Student2(int age) {
		super();
		this.age = age;
	}
	
	public void study() {}
	public void exam() {}
	public void work() {}
	
	private int aaa() {
		return 0;
	}
	
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
	}
}

输出结果:

com.qf.Day34.Student2
---Package---
com.qf.Day34

---Superclass---
com.qf.Day34.Person2

---Interfaces---
java.io.Serializable
java.lang.Runnable
java.lang.Comparable

---Fields---
name
sex
money

---Fields---
name
age
sex
score

---Methods---
run
compareTo
study
exam
work
sleep
eat
wait
wait
wait
equals
toString
hashCode
getClass
notify
notifyAll

---Methods---
run:void
compareTo:int
study:void
aaa:int
exam:void
work:void

---Constructors---
com.qf.Day34.Student2:int
com.qf.Day34.Student2:java.lang.String
com.qf.Day34.Student2:


com.qf.Day34.Student2@3d4eac69
com.qf.Day34.Student2@3d4eac69

17.4 工厂设计模式

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

public class TestNewInstance {

	public static void main(String[] args) throws Exception {
		//1.手工new对象
		Teacher t = new Teacher();
		t.name = "Tom";

		
		//2.反射 通过类对象创建类的对象
		Class c = Teacher.class;
		Teacher t2 = (Teacher)c.newInstance();
		t2.name = "Alex";
		System.out.println(t2.name);
	
		//3.通过配置文件,输入流进行创建对象
		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 Teacher{
	String name;
	String sex;
	Integer age;
	
	public Teacher() {
		super();
	}

	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("在算分。。。");
	}
	
}

输出结果:

Alex
com.qf.Day34.Teacher@7852e922
import java.lang.reflect.Method;

public class TestInvokeMethod {

	public static void main(String[] args) throws Exception {
		//反射 类的对象
		Object o = createObject("com.qf.Day35.Student");
		//类对象
		Class c = o.getClass();
		
		//name方法名     parameterTypes参数列表类型
		Method m = c.getMethod("study", null);
		//通过invoke方法,执行某个实例方法  参数:Object-》所需对象,args-》调用方法所需的实参
		m.invoke(o, null);
		
		//调用方法,无法调用私有方法
		Method m1 = c.getMethod("study", int.class);
		Object result = m1.invoke(o, 3);//接收方法返回值,如果是基本类型,则转换为包装
		System.out.println(result);
//		System.out.println(c.getMethod("study", int.class).invoke(o, 5));
		
		Method m2 = c.getMethod("exam", String.class , int.class , double.class);
		m2.invoke(o, "tom" , 50 , 90D);
		
		
		//获得自身方法,包含私有
		Method m3 = c.getDeclaredMethod("calc",null);
		
		m3.setAccessible(true);//注意:反射是一种Java底层技术,可以取消语言检查,突破封装
		m3.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 socre;
	
	public Student() {}

	public Student(String name, Integer age, String sex, Double socre) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.socre = socre;
	}
	
	public void study() {
		System.out.println("学习中。。。");
	}
	public int study(int hours) {
		System.out.println("学习了"+hours+"小时");
		return hours;
	}
	public void exam(String a , int b , double c) {
		System.out.println(a+"考了"+b+"分钟,得分"+c);
	}
	private void calc() {
		System.out.println("calc");
	}
}

输出结果:

学习中。。。
学习了3小时
3
tom考了50分钟,得分90.0
calc
public class TestInvokeAnything {

	public static void main(String[] args) throws Exception {
		//invokeAAny()-->执行方法
		//对象(Object)、方法名称(String)、形参(Class)、实参(Object)
		Object o = createObject("com.qf.Day35.Student");
		invokeAny(o , "exam" , new Class[] {String.class,int.class,double.class},"alex",60,99D);
		invokeAny(o,"study",null,null);
		invokeAny(o,"study",new Class[] {int.class},10);
		
	}

	public static void invokeAny(Object obj , String methodName ,Class[] types,Object... args) throws Exception {
		//使用反射技术执行任何方法
		//类对象
		Class c = obj.getClass();
		//获得方法的对象
		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;
		}
}

输出结果:

alex考了60分钟,得分99.0
学习中。。。
学习了10小时

17.5 单例模式

17.5.1 单例模式1

  • 单例(Singlethon):只允许创建一个该类的对象;
  • 方式1:饿汉式(类加载是创建,天生线程安全)

17.5.2 单例模式2

  • 方式2:懒汉式(使用时创建,线程不安全,加同步)

17.5.3 单例模式3

  • 方式3:懒汉式(使用时创建,线程安全)
/*
 * 单例模式,一个类只能创建一个对象
 * */
public class TestSingleton {

	public static void main(String[] args) {
		Singleton1 s1 = Singleton1.getInstance();
		System.out.println(s1   );

		Singleton2 s2 = Singleton2.getInstance();
		Singleton2 s3 = Singleton2.getInstance();
		Singleton2.instance = null;
		Singleton2 s4 = Singleton2.getInstance();
		System.out.println(s2   );
		System.out.println(s3   );
		System.out.println(s4   );//线程不安全,可能会创建不同对象
		
		
		Singleton3 s5 = Singleton3.getInstance();
		Singleton3 s6 = Singleton3.getInstance();
		System.out.println(s5);
		System.out.println(s6);
	
	}

}
//饿汉式:天生线程安全(无锁),类加载时创建(不用的时候也被迫创建了,占用资源)
class Singleton1{
	private static final Singleton1 instance = new Singleton1();
	
	private Singleton1() {}
	
	public static Singleton1 getInstance() {
		return instance;
	}
}

//懒汉式:使用时创建,天生线程不安全(需要加同步锁),效率低
class Singleton2{
	static Singleton2 instance = null;
	
	private Singleton2() {}
	
	public static Singleton2 getInstance() {
		if(instance == null) {
			instance = new Singleton2();
		}
		return instance;
	}
}

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

输出结果:

com.qf.Day35.Singleton1@7852e922
com.qf.Day35.Singleton2@4e25154f
com.qf.Day35.Singleton2@4e25154f
com.qf.Day35.Singleton2@70dea4e
com.qf.Day35.Singleton3@5c647e05
com.qf.Day35.Singleton3@5c647e05

17.6 总结

  • 类对象:
    Class对象,封装了一个类的所有信息;程序运行中,可通过Class对象获取类的信息;

  • 获取类对象的三种方式:
    Class c = 对象.geiClass();
    Class c = 类名.class;
    Class c = Class.forName(“包名.类名”);

  • 工厂模式:
    主要用于创建对象,通过反射进行工厂模式的设计,完成动态的对象创建;

  • 单例模式:
    Singleton,只允许创建一个该类的对象;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值