javase day23

反射
在这里插入图片描述
在这里插入图片描述
耦合度:多个模块之间的关联或者依赖关系(低耦合)
解析类:用于找到字节码对象以产生实例对象的过程—反射
Class------代表类的类----代表.class的类
Field—代表属性的类
Method—代表方法的类
Construct----代表构造方法的类
Annotation—代表注解的类
Package----代表包的类

获取字节码对象的方式
1、通过类名.class获取字节码对象
2、通过对象.getclass获取对象实际创建类的字节码对象
3、Class.forName(全路径名)—获取类的字节码对象

反射的缺点
1、打破封装的原则
2、跳过泛型的类型检测

package cn.tedu.classx;
import java.util.List;
public class ClassDemo1 {
	public static void main(String[] args) throws ClassNotFoundException {
		//获取String的字节码对象
		//1、类名.class
		Class<String> clz1=String.class;
		//接口的字节码对象
		Class<List> clz2=List.class;
		//基本类型的字节码对象
		Class clz3=int.class;
		//2、对象.getClass
		String str="abc";
		Class<String> clz=(Class<String>) str.getClass();
		//通知对象获得integer的字节码对象
		Integer in=12;
		Class<Integer> clz4=(Class<Integer>) in.getClass();
		//3、Class.forName(全路径名)---获取到对应的字节码对象
		Class clz5=Class.forName("java.util.Date");
		System.out.println(clz5);
	}
}

public class ClassDemo2 {
	public static void main(String[] args) throws Exception {
		//先获取String的字节码对象
		Class <String> clz=String.class;
		/*//获取实例对象
		//newInstance()---默认在调用类的无参构造
		String str=clz.newInstance();
		str="abc";
		System.out.println(str);*/
		//通过字节码对象调用到String类的有参构造
		Constructor c=clz.getConstructor(char[].class);//传入构造方法参数类型的字节码对象
		//获取到的有参构造调用newInstance()传入实际参数构造实例对象
		String str=(String)c.newInstance(new char[] {'1','2','a'});
		//获取构造方法
		Constructor c1=clz.getConstructor(String.class);
		//传参---构建实例对象
		String str1=(String) c1.newInstance("abc");
		//通过Integer的全路径名获取integer的实例对象并赋值
		//通过class.forname()获取字节码对象
		Class<Integer> clz1=(Class<Integer>) Class.forName("java.lang.Integer");
		//获取有参构造方法new Integer(int)
		Constructor c2=clz1.getConstructor(int.class);
		//传参--构建实例对象
		Integer in=(Integer) c2.newInstance(123);
		System.out.println(in);
	}
}

构造方法的类

public class ClassDemo3 {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		//获取字节码对象
		Class<String> clz=String.class;
		/*//获取构造方法
		//Constructor c=clz.getConstructor(char[].class,boolean.class);//报错不可用
		//获取指定的构造方法(忽略访问权限修饰符)
		Constructor c=clz.getDeclaredConstructor(char[].class,boolean.class);
		//暴力破解(可以操作特殊的构造方法)
		c.setAccessible(true);
		//传参,构建实例对象
		String str=(String) c.newInstance(new char[] {'2'},true);
		System.out.println(str);*/
		
		//获取String类里的所有构造方法
		Constructor[] cs=clz.getDeclaredConstructors();
		for (Constructor constructor : cs) {
			System.out.println(constructor);
		}
		
	}
}

属性的类

public class ClassDemo4 {
	public static void main(String[] args) throws Exception {
		//String的字节码对象
		Class<String> clz=String.class;
		//获取指定的属性--hash
		Field f=clz.getDeclaredField("hash");
		//暴力破解
		f.setAccessible(true);
		//字符串对象--属性
		String str="abc";
		/*//给对象的属性赋值--给Str对象的hash属性赋值为123
		f.set(str, 123);
		//取值---获取Str对象的hash属性的值
		System.out.println(f.get(str));
		System.out.println(str.hashCode());*/
		//获取字符串的所有属性
		Field[] fs=clz.getDeclaredFields();
		for (Field field : fs) {
			System.out.println(field);
		}
	}
}

属性的类

public class ClassDemo5 {
	public static void main(String[] args) throws Exception {
		//获取字节码对象
		Class<String> clz=String.class;
		//获取指定的方法
		Method m=clz.getDeclaredMethod("charAt", int.class);
		String s="sfasffsdf";
		//调用方法---s.charAt(3)
		char c=(char) m.invoke(s, 3);
		System.out.println(c);
	}
}

public class ClassDemo6 {
	public static void main(String[] args) {
		/*//枚举类的字节码对象
		Class<Demo> clz=Demo.class;
		//返回枚举常量
		Demo[] ds=clz.getEnumConstants();
		for (Demo demo : ds) {
			System.out.println(demo);
		}*/
		//
		Class<String> clz=String.class;
		//没有枚举常量返回的是一个null
		//String[]ss=clz.getEnumConstants();
		/*//返回的是实现的接口
		Class[] cs=clz.getInterfaces();
		for (Class class1 : cs) {
			System.out.println(class1);
		}*/
		//字节码对象对应类的全路径名
		//System.out.println(clz.getName());
		//返回字节码对象对应类的包的名称
		//System.out.println(clz.getPackage());
		//字节码对象对应类的类名
		System.out.println(clz.getSimpleName());
		//得到父类的字节码对象
		System.out.println(clz.getSuperclass());
	}
}
//
enum Demo{
	A,B,C,D;//枚举常量,对象
}
public class FiledDemo {
	public static void main(String[] args) throws Exception {
		//获取字节码对象
		Class<String> clz=String.class;
		//可以获取指定的属性
		Field f=clz.getDeclaredField("serialVersionUID");
		//返回属性的数据类型
		System.out.println(f.getType());
	}
}

public class MethodDemo {
	public static void main(String[] args) throws NoSuchMethodException, SecurityException {
		Class<String> clz=String.class;
		//获取指定的方法
		//Method m=clz.getDeclaredMethod("getBytes", String.class);
		Method m=clz.getDeclaredMethod("getBytes", Charset.class);
		/*//返回的是编译时的异常
		Class[] cs=m.getExceptionTypes();
		for (Class class1 : cs) {
			System.out.println(class1);
		}*/
		//获取参数类型的字节码放到一个数组
		Class[] cs=m.getParameterTypes();
		for (Class class1 : cs) {
			System.out.println(class1);
		}
		
	}
}

public class ClassDemo7 {
	public static void main(String[] args) throws Exception {
		List<String> list=new ArrayList<String>();
		list.add("abc");
		//获取list接口字节码对象
		Class<List> clz=(Class<List>) list.getClass();
		//获取指定的方法
		Method m=clz.getDeclaredMethod("add", Object.class);
		//调用方法
		m.invoke(list, 123);
		System.out.println(list);
	}
}

反射克隆

package cn.tedu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
*@author 作者:
*@version 创建时间:2020年11月30日下午10:36:01
*@description 描述:通过反射实现克隆
*/
public class ReflectText {
	public static void main(String[] args) throws Exception {
		Person p1=new Person("lili",10);
		/*p1.name="lili";
		p1.age=10;*/
		Person p2=(Person)clone(p1);
		System.out.println(p2.name+","+p2.age);
	}
	//实现Clone方法
	public static Object clone(Object obj) throws Exception {
		/*//1、获取字节码对象
		Class<Object> clz=(Class<Object>) obj.getClass();
		//2、获取实例对象--新对象
		Object o1=clz.newInstance();
		//3、获取原对象的所有属性
		Field[] fs=clz.getDeclaredFields();
		//4、把原对象的属性赋值给新对象
		for (Field f : fs) {
			//暴力破解
			f.setAccessible(true);
			//获取元素对象的属性
			Object o2=f.get(obj);
			//所有属性赋值给新对象
			f.set(o1, o2);
		}
		//5、返回新对象
		return o1;*/
		
		//1、获取字节码对象
		Class<Object> clz=(Class<Object>) obj.getClass();
		//2、获取构造方法--保证一定能拿到构造方法
		Constructor c=clz.getDeclaredConstructors()[0];
		//返回拿到的这个构造方法上所有的参数类型的字节码对象
		Class[] cs=c.getParameterTypes();//String int
		//Object的数组
		Object[] os=new Object[cs.length];//null 0
		//遍历参数类型的数组
		for (int i = 0; i < cs.length; i++) {
			//判断参数类型是否是基本类型
			if(cs[i].isPrimitive()) {
				//
				if(cs[i]==byte.class||cs[i]==short.class||cs[i]==int.class) {
					os[i]=0;
				}
				if(cs[i]==char.class){
					os[i]='\u0000';
				}
				if(cs[i]==long.class) {
					os[i]=0L;
				}
				if(cs[i]==float.class) {
					os[i]=0.0F;
				}
				if(cs[i]==double.class){
					os[i]=0.0;
				}
				if(cs[i]==boolean.class) {
					os[i]=false;
				}
			}else {//引用类型
				os[i]=null;
			}
		}
		//2、获取实例对象--新对象
		Object o1=c.newInstance(os);
		//3、获取原对象的所有属性
		Field[] fs=clz.getDeclaredFields();
		//4、把原对象的属性赋值给新对象
		for (Field f : fs) {
			//暴力破解
			f.setAccessible(true);
			//获取元素对象的属性
			Object o2=f.get(obj);
			//所有属性赋值给新对象
			f.set(o1, o2);
		}
		//5、返回新对象
		return o1;
	}
}
class Person{
	String name;
	int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
}

注解:
给计算机看的注释
注解属性默认被public static final共同修饰
支持的属性类型–基本数据类型、String、Class、Annotation、枚举以及对应形式的一维数组表现i形式
元注解:
用于控制、限制注解的使用情况(给注解的注释)
@Target—控制注解可以在什么位置使用
@Retention—控制注解的级别
@Documented—可以让注解随着类一起文档化出去
@Inherited—可以让子类依然具有注解

package cn.tedu.annox;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*@author 作者:
*@version 创建时间:2020年12月3日下午8:19:50
*@description 描述:自定义注释
*/
@First()
public class AnnoDemo1 {
	@First()
	int i=1;
	@First()
	public static void main(@First()String[] args) {
		@First()
		int j=10;
		System.out.println(First.i);//First.i=10报错
	}
	
}
/*@First(d=1.2,arr= {1,2,2})
public class AnnoDemo1 {
	@First(d=1.2,arr= {1,2,2})
	int i=1;
	@First(d=1.2,arr= {1,2,2})
	public static void main(@First(d=1.2,arr= {1,2,2})String[] args) {
		@First(d=1.2,arr= {1,2,2})
		int j=10;
		System.out.println(First.i);//First.i=10报错
	}
	
}*/

//自定义注释
//@Target(ElementType.TYPE)
//@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
@Inherited
@interface First{
	//默认被public static final共同修饰
	public static final int i=10;
	//double d();//申明属性没有赋值
	//Object类型不在支持的范围之内
	//Object od;
	//int[] arr();//一维数组
}

生成注释文档
步骤:
project–generate javadoc–选包选Java文件–(D:\Program Files\Java\jdk1.8.0_241\bin\javadoc.exe)

package cn.tedu.annox;
import java.lang.annotation.Documented;
@Documented
public @interface Third {

}
package cn.tedu.annox;

@Third
public class AnnoDemo2 {
	public static void main(String[] args) {
		
	}
}

单例设计模式
一个类只能产生一个实例对象
饿汉式:直接生成本类对象
懒汉式:需要调用对象时才生成对应的对象,但是会存在多线程并发安全
去了解其它单例模式的实现方式

package cn.tedu.singlex;
/**
*@author 作者:
*@version 创建时间:2020年12月3日下午9:45:23
*@description 描述:
*/
public class SingleDemo {
	public static void main(String[] args) {
		//外界可以获取唯一的对象
		//TaskManager tm=TaskManager.getInstance();//饿汉式和懒汉式
	}
}
//任务管理器---只能创建一个对象
/*//饿汉式实现方式
class TaskManager{
	//构造方法私有化
	private TaskManager() {}
	//创建对象
	private static TaskManager tm=new TaskManager();
	//给外界获取的方法
	public static TaskManager getInstance() {
		return tm;//把唯一一个对象进行返回
	}
	//调用这个静态方法对象就会创建
	public static void m() {}
}*/

/*//懒汉式实现方式
class TaskManager{
	//构造方法私有化
	private TaskManager() {}
	//创建对象
	private static TaskManager tm=null;
	//给外界获取的方法
	public static TaskManager getInstance() {
		//判断对象是否为null
		if(tm==null) {//没有创建过对象
			tm=new TaskManager();//创建唯一的对象
		}
		return tm;
	}
	//调用这个静态方法对象就会创建
	public static void m() {}
}*/

//枚举实现方式
enum TaskManager{
	tm;
}

JVM参数
栈:用于计算的 是被线程单独使用的
堆:存储的时对象 是被所有线程共享的
方法区:原名永久代 方法区挪到堆里 存储的是类的所有信息 被所有的线程共享
本地方法栈:用于计算本地方法 被线程单独使用
PC计数器:用于存储计算机/程序的指令以及调度 被线程单独使用

-X 参数—标准参数
-Xxxx 参数—非标准参数
-Xss 128KB—指定的是栈内存的大小
-Xmx 10M–对应的是最大内存的大小
-XX:+PrintGCDetails—指明GC执行的详细细节

package cn.tedu.jvm;
/**
*@author 作者:
*@version 创建时间:2020年12月3日下午10:11:17
*@description 描述:
*/
/*
 * 右键run as----run configurations---arguments---vm arguments输入-Xss 128KB--指定占内存的大小
 */
public class JVMDemo {
	static int count=0;
	public static void main(String[] args) {
		sum(100000);
		int[] arr=new int[1024*1024*10];
	}
	public static int sum(int n) {
		System.out.println(count++);
		if(n==1) {
			return 1;
		}
		return sum(n-1)+n;
	}
}

步骤:右键run as----run configurations—arguments—vm arguments输入-Xss 128KB–指定占内存的大小
在这里插入图片描述

windows 操作界面 输入java -X(相关详细内容)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值