文章目录
反射【重点重点重点】和单例
1. 单例
1.1 为什么要使用单例
要求当前类在整个程序的运行过程中有且只有一个类对象!!!
一般作为单例的对象都是一些核心的处理数据或者业务逻辑的对象!!!
Servlet
多线程编程中使用非常多。
例如:
在项目处理数据,控制数据的类,一般会采用单例模式,防止数据出现冲突和冗余问题。并且极有可能导致共享资源问题
1.2 代码实现
package com.qfedu.a_single;
class SingleDog {
private static SingleDog sd = null;
private SingleDog() {}
public static SingleDog getInstance() {
// 反射告诉你这是什么???
synchronized (SingleDog.class) {
if (null == sd) {
sd = new SingleDog();
}
}
return sd;
}
}
class SingleType {
private static SingleType st = new SingleType();
private SingleType() {}
public static SingleType getInstance() {
return st;
}
}
/*
问题1:
目前在代码中创建当前对象SingleDog的方式有且只有new关键字+构造方法可以使用
但是这种方式,是任何一个程序员都可以随意调用的,无法满足单例模式的基本要求
公告:
该对象我已经new过了,你们不能new
匿名: 你是不是傻子
解决:
从语法角度断绝new+构造方法组合
构造方法私有化
问题2:
私有化构造方法之后,类外没有创建对象的能力,这不符合单例模式需求。
分析:
1. 类外需要一个对象
2. 构造方法私有化了
私有的方法类内可以使用
留给类外可以调用的方法有哪些?
普通成员方法不能使用,因为【没有对象】
静态成员方法可以使用类名调用,因为【不需要对象】
思考 是否可以让静态成员方法创建对象,提供给类外使用
1. 静态成员方法需要类外使用 public
2. 静态成员方法 需要使用 static修饰
3. 获取一个类对象且是一个SingleDog对象,返回值类型SingleDog
4. 方法名 getInstance
5. 类内的构造方法没有参数,所有该方法不需要参数
public static SingleDog getInstance()
问题3:
发现南辕北辙,通过目前的方式依然得到的是不同对象,因为调用getInstance
是new了不同的对象。
分析:
也不是不让你new对象,但是只能new一次对象,之后调用该getInstance方法,只能
返回之前new对象的空间首地址。
这里需要保存第一次创建对象的空间首地址!!!
成员变量
getInstance方法是一个static方法,这家伙能用非静态成员变量?[没有对象]
局部变量
目前还是一个分母,没法用
静态成员变量
可以使用
static
SingleDog
private
private static SingleDog sd = null;
问题4:
因为涉及到多线程问题,需要考虑加锁
类锁!!!
*/
public class Demo {
public static void main(String[] args) {
System.out.println(SingleType.getInstance());
System.out.println(SingleType.getInstance());
System.out.println(SingleType.getInstance());
System.out.println(SingleType.getInstance());
System.out.println(SingleType.getInstance());
System.out.println(SingleType.getInstance());
System.out.println(SingleType.getInstance());
}
}
2. 反射【重中之重】
2.1 反射是原理
Java文件通过Javac.exe编译之后,生成对应当前文件中所有class, 对应的.class
Java文件可以认为是包含了当前Java程序的所有内容,包含
构造方法Constructor
成员方法Method
成员变量Field
注解Annotation
对应当前Java文件的.class字节码文件包含了当前Java程序的所有内容,只不过是对应的当前Java程序的二进制文件。
2.2 获取Class类对象
Class Class.forName(String 完整的包名.类名);
1. 可以通过指定的包名.类名获取对应当前类的Class类对象
2. 该方法可以帮你加载指定类。
Class 类名.class;
通过类名获取对应的Class类对象
Class 类对象.getClass();
通过类对象获取对应的Class类对象
2.3 获取Constructor类对象
Constructor[] getConstructors();
/*
获取当Class类对象对应的所有非私有化构造方法,返回值是一个构造方法类对象数组
*/
Constructor[] getDeclaredConstructors();
/*
【暴力反射】
获取当Class类对象对应的所有构造方法,返回值是一个构造方法类对象数组
*/
Constructor getConstructor(Class... initArgumentTypes);
/*
获取指定初始化参数数据类型的非私有化构造方法类对象
Class: 这里要求是Class类对象
例如: int.class String.class
... : 不定长参数 这里对于参数个数不限制,但是要求全部都是Class类型
例如:
无参数 (null)
一个参数 (int.class)
两个参数 (int.class, String.class)
*/
Constructor getDeclaredConstructor(Class... initArgumentTypes);
/*
【暴力反射】
获取指定初始化参数数据类型的任意构造方法类对象
Class: 这里要求是Class类对象
例如: int.class String.class
... : 不定长参数 这里对于参数个数不限制,但是要求全部都是Class类型
例如:
无参数 (null)
一个参数 (int.class)
两个参数 (int.class, String.class)
*/
Object newInstance(Object... initArguments);
/*
使用Constructor类对象调用,传入当前Constructor构造方法类对象需要的实际参数,创建对象!!!
Object: 当前构造方法需要的实际参数
... : 不定长参数
无参数: (null)
一个参数: (10)
两个参数: (10, "为所欲为")
*/
2.4 获取Method类对象
Method[] getMethods();
/*
获取类内所有非私有化成员方法类对象数组
注意
包括从父类继承而来可以使用的成员方法!!!
*/
Method[] getDeclaredMethods();
/*
【暴力反射】
获取类内所有成员方法,包括私有成员方法类对象数组
注意:
不包括从父类继承而来的方法
*/
Method getMethod(String methodName, Class... argumentTypes);
/*
获取指定MethodName,以及对应参数类型的非私有化成员方法
methodName:方法名
Class: Class类型,对应当前方法的参数类型
...: 不定长参数,因为参数的个数不确定
无参数("game", null);
String参数("game", String.class)
*/
Method getDeclaredMethod(String methodName, Class... argumentTypes);
/*
【暴力反射】
获取指定MethodName,以及对应参数类型任意修饰的成员方法
methodName:方法名
Class: Class类型,对应当前方法的参数类型
...: 不定长参数,因为参数的个数不确定
无参数("game", null);
String参数("game", String.class)
*/
Object invoke(Object obj, Object... args);
/*
使用Method类对象调用,执行对应Method类对象方法
obj: 调用当前方法的类对象
args: 对应当前方法的实际参数
例如:
method.invoke(p1, null);
method.invoke(p1, "LOL");
*/
2.5 获取Field类对象
Field[] getFields();
/*
获取类内所有非私有化成员变量类对象
*/
Field[] getDeclaredFields();
/*
获取类内所有成员变量,包括私有化成员变量
*/
Field getField(String fieldName);
/*
获取指定成员变量名对应的非私有化成员变量Field类对象
*/
Field getDeclaredField(String fieldName);
/*
获取指定成员变量名对应的任意修饰的成员变量类对象,包括私有化成员变量
*/
void set(Object obj, Object value);
/*
设置指定类对象中的成员变量数据
obj:操作的类对象
value: 给予成员变量的数值
*/
Object get(Object obj);
/*
获取指定类对象中成员变量数据
obj: 指定类对象
*/
2.6 给予暴力反射操作权限
void setAccessible(boolean flag);
/*
给予暴力反射权限 参数为true
*/
希望大家关注我一波,防止以后迷路,有需要的可以加我Q讨论互相学习java ,学习路线探讨,经验分享与java Q:2415773436