Java学习笔记day24

反射

简介

JDK1.5引入
优点:提高了代码的灵活性,使java语言从静态语言变为半动态语言
创建对象:
	先创建类,在类中定义属性,定义方法,使用new关键字创建该类对象
反射使用场景:
	1.使用第三方类库,可以创建其对象,但是不知道对象拥有的属性与方法,如果想获取,此时就可以通过反射进行获取
	2.使用第三方类库,只知道类名,但是不知道类中有什么,可以使用反射进行获取与使用
	3.使用第三方类库,只知道类所在的包名与类名,但是想操作,可以使用反射对其进行操作

类对象

概念
一个类被JVM加载时,会生成一个类对象
	
类对象中包含了该类的属性,方法,构造函数,父类,父接口等信息

注意:
	一个类只会被JVM加载一次,所以一个类的类对象只有一个
	通过new关键字创建出来的对象,称为类的对象,又名实例对象,与类对象不是一个东西
获取类对象的方式
方式1: 
	通过类的实例对象.getClass()获取类对象
方式2: 
	通过类名获取类对象
	类名.class
方式3: 
	通过Class类提供的静态方法获取
	Class.forName("包名.类名");
类对象的常用方法
概述: 获取该类信息

获取类的全名称(包名+类名)
	String getName()
获取类名
	String getSimpleName();
获取类加载器
	ClassLoader getClassLoader();
获取父类
	Class getSuperclass();
获取父接口
	Class[] getInterfaces();
获取包
	Package getPackage();
		方法:
			getName()获取包名
通过类对象创建类的实例对象
	Object newInstance();
	注意1: 如果该类中没有无参构造函数,那么此时方法将出现NoSuchMethodException异常
	注意2: 如果该类的无参构造函数访问权限不足,此时方法将出现IllegalAccessException异常
	
获取属性
	获取类的所有公共属性
	注意:可以获取到父类的公共属性
		Field[] getFields();
		
	获取本类的所有属性
	注意:只能获取本类的所有属性
		Field[] getDeclaredFields();
		
	获取指定的属性
		Field getDeclaredField("属性名");
	
获取构造函数
	获取类的所有公共构造函数
		Constructor[] getConstructors();
	获取类的所有构造函数
		Constructor[] getDeclaredConstructors();
	获取类的指定构造函数
		Constructor<?> getDeclaredConstructor(获取构造函数的参数列表的类对象列表);
		
获取方法
	获取类中所有公共方法
		Method[] getMethods();
		注意:可以获取到父类提供的公共方法
		
	获取类中所有方法
		Method[] getDeclaredMethods();
		注意:只能获取该类的所有方法
		
	获取类中指定方法
		Method getDeclaredMethod(String name, Class... p)
		参数1: 方法名
		参数2: 该方法形参列表对应的类对象列表
		如:
			public void test(double d,String s,int i){
			
			}
			Method 方法对象 = 类对象.getDeclaredMethod("test",
			double.class,String.class,int.class);
获取注解
package demo01;

public class Test {
	public static void main(String[] args) throws Exception {
		Person p = new Person();
		//获取类对象方式1
		//使用实例对象.getClass();
		Class class1 = p.getClass();
		//获取类对象方式2
		//使用类名.class;
		Class class2 = Person.class;
		//获取类对象方式3
		//使用Class类提供的静态方法
		//Class.forName("包名.类名");
		Class class3 = Class.forName("demo01.Person");
		//证明只有一个类对象
		System.out.println(class1 == class2);
		System.out.println(class2 == class3);
	}
}

运行结果

package demo01;

public class Test01 {
	public static void main(String[] args) throws Exception {
		Class c = Person.class;
		String name = c.getName();
		System.out.println("获取类的全名称: " + name);
		String simpleName = c.getSimpleName();
		System.out.println("获取类名: " + simpleName);
		//获取类加载器
		//暂时没用,后期需要在项目中使用src下配置文件时
		//可以使用类加载获取
		ClassLoader loader = c.getClassLoader();
		System.out.println("类加载器: " + loader);
		//获取父类
		Class superclass = c.getSuperclass();
		System.out.println("父类: " + superclass);
		Class[] interfaces = c.getInterfaces();
		for (Class c0 : interfaces) {
			System.out.println("实现的接口: " + c0.getName());
		}
		Package package0 = c.getPackage();
		System.out.println("类所在的包: " + package0.getName());
		
		//通过类对象创建该类的实例对象
		//newInstance调用的是该类的无参构造
		//注意1:如果该类中没有无参构造函数,那么此时方法将出现NoSuchMethodException异常
		//注意2:如果该类的无参构造访问权限不足,此时方法将出现IllegalAccessException异常
		Person p = (Person) c.newInstance();
		System.out.println("通过类对象创建的类的实例对象: " + p);
	}
}

运行结果

Field类

常用方法: 
	修改对象的属性值
	void set(对象, 修改后的值);
	
	获取对象的属性值
	Object get(对象);
	
	略过访问权限修饰符
	void setAccessible(true);
	
	获取属性名
	String getName();
package demo01;

import java.lang.reflect.Field;

public class Test02 {
	public static void main(String[] args) throws Exception {
		Class c = Person.class;
		
		//获取类的所有公共属性
		//注意:可以获取到父类的公共属性
		Field[] fields01 = c.getFields();
		for (Field f : fields01) {
			System.out.println("公共属性: " + f.getName());
		}
		
		//获取本类的所有属性
		//注意:只能获取本类的所有属性
		Field[] fields02 = c.getDeclaredFields();
		for (Field f : fields02) {
			System.out.println("所有属性: " + f.getName());
		}
		
		//获取父类的类对象
		Class superclass = c.getSuperclass();
		Field[] fields03 = superclass.getDeclaredFields();
		for (Field f : fields03) {
			System.out.println("父类所有属性: " + f.getName());
		}
		
		//获取指定的属性
		Field field01 = c.getDeclaredField("age");
		Person p = (Person) c.newInstance();
		System.out.println("修改前: " + p);
		//修改对象的属性值
		//参数1:要修改的对象
		//参数2:修改后的值
		field01.set(p, 18);
		System.out.println("修改后: " + p);
		//获取对象的属性值
		int age = (int) field01.get(p);
		System.out.println("获取到的属性值为: " + age);
		
		//获取指定的属性
		Field field02 = c.getDeclaredField("name");
		//略过访问权限修饰符
		field02.setAccessible(true);
		field02.set(p, "张三");
		System.out.println("修改后: " + p);
	}
}

运行结果

Constructor类

常用方法:
	创建对象
		T newInstance(实参列表);
	略过访问权限修饰符
		void setAccessible(true);
package demo01;

import java.lang.reflect.Constructor;

public class Test03 {
	public static void main(String[] args) throws Exception {
		Class c = Person.class;
		
		//获取类的所有公共构造函数
		//此处没有父类的构造函数,因为子类无法继承父类构造函数
		Constructor[] constructors01 = c.getConstructors();
		for (Constructor constructor : constructors01) {
			System.out.println("公共构造函数: " + constructor);
		}
		
		//获取类的所有构造函数
		Constructor[] constructors02 = c.getDeclaredConstructors();
		for (Constructor constructor : constructors02) {
			System.out.println("所有构造函数: " + constructor);
		}
		
		//获取公共空参构造函数
		Constructor<Person> constructor01 = c.getDeclaredConstructor();
		Person p01 = constructor01.newInstance();
		System.out.println(p01);
		
		//获取私有2参构造函数
		Constructor<Person> constructor02 = c.getDeclaredConstructor(String.class, String.class);
		constructor02.setAccessible(true);
		Person p02 = constructor02.newInstance("张三", "男");
		System.out.println(p02);
	}
}

运行结果

Method类

常用方法:
	作用:执行方法
	Object invoke(Object obj, Object... args);
	参数:
		obj:执行该方法的对象
		args:实参列表
	返回值:
		执行的方法的返回值
		
	略过访问权限修饰符
	void setAccessible(true);
package demo01;

import java.lang.reflect.Method;

public class Test04 {
	public static void main(String[] args) throws Exception {
		Class c = Person.class;
		Person p = new Person();
		
		//获取所有的公共方法
		//可以获取到父类或实现接口的公共方法
		Method[] methods01 = c.getMethods();
		for (Method method : methods01) {
			System.out.println("公共方法: " + method);
		}
		
		//获取本类的所有方法
		Method[] methods02 = c.getDeclaredMethods();
		for (Method method : methods02) {
			System.out.println("所有方法: " + method);
		}
		
		//获取私有的eat方法
		Method m01 = c.getDeclaredMethod("eat");
		//略过访问权限修饰符
		m01.setAccessible(true);
		//执行方法
		m01.invoke(p);
		
		//获取指定的setName方法
		Method m02 = c.getDeclaredMethod("setName", String.class);		
		//执行setName方法
		m02.invoke(p, "张三");
		System.out.println(p);
		
		//获取getName方法
		Method m03 = c.getDeclaredMethod("getName");
		//执行方法
		String name = (String) m03.invoke(p);
		System.out.println(name);
	}
}

运行结果

Annotation类

设计模式

简介

一套被反复使用,多数人知道,经过分类,代码设计经验的总结
简单的理解为: 设计模式就是解决固定问题的方案
相关书籍: Gof的<<设计模式>>一共有23种设计模式

设计模式法则

单一职责: 一个方法或接口或类...只干一件事
开闭原则: 对扩展开放,对修改关闭
里式替换
依赖倒置
接口隔离
迪米特法则

单例模式

解决的问题:
	让一个类只能产生一个对象
分类:
	饿汉式
		步骤:
			1.私有构造函数,此时外部就无法通过new调用构造函数创建对象
			2.在该类中提供一个私有的静态的不可修改的该类对象
			3.提供公共静态方法,该方法返回步骤2的对象
			以后外部需要该类对象只能使用类名.步骤3提供的静态方法得到
		优点: 线程安全
		缺点: 浪费内存
		
	懒汉式
		线程不安全
			步骤:
				1.私有构造函数
				2.在该类中声明一个私有的静态的该类对象
				3.提供公共静态方法,方法中
					判断步骤2的对象是否为空,如果为空创建对象,赋值给该属性,再返回该类对象,如果不为空直接返回
			优点:不浪费内存
			缺点:只能应用于单线程情况下
			
		线程安全的
			使用锁
                步骤:
                    1.私有构造函数
                    2.在该类中声明一个私有的静态的该类对象
                    3.提供同步的公共静态方法,方法中
                        判断步骤2的对象是否为空,如果为空创建对象,赋值给该属性,再返回该类对象,如果不为空直接返回
                优点:不浪费内存,线程安全
                缺点:在多线程的情况下比饿汉式效率低
			
	静态内部类模式

工厂模式

解决的问题:
	一个方法只能产生一种对象
例子:
	一个家具厂通过制作方法可以制作椅子,桌子,衣柜,茶几等

枚举(了解)

作用: 限定值的取值范围
注意:
	枚举是一种引用数据类型
	枚举变量的值必须是枚举常量
	枚举中可以定义普通的属性,方法与私有的构造函数
	如果枚举中只有枚举常量,此时可以忽略分号不写,多个枚举常量直接使用逗号隔开
	如果枚举中定义了普通属性等,此时枚举常量最后需要使用分号
	
枚举的定义:
	访问权限修饰符 enum 枚举名{
		枚举常量名1,枚举常量名2,...
	}
枚举的使用:
	声明变量
	作为形参
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值