什么是类对象
- 类的对象:基于某个类new出来的对象,也称为实例对象
- 类对象:类加载的产物,封装了一个类的所有信息(类名,父类,接口,属性,方法,构造方法)
- 注意:使用-verbose:class 可以显示累的加载过程
获取类对象的方法
- 通过类的对象,获取类对象
Student s= new Student();
Class c=s.getClass(); - 通过类名获取类对象
Class c=类名.class - 通过静态方法获取类对象
Class c=Class.forName(“包名.类名”);
public class Demo01 {
public static void main(String[] args) throws Exception{
//1.通过类的对象,获取类对象
Student student = new Student();
Class<?> class1 = student.getClass();
System.out.println(class1.hashCode());
//2.通过类名获取类对象
Class<?> class2 = Student.class;
System.out.println(class2.hashCode());
//3.通过静态方法获取类对象【推荐使用】
Class<?> class3 = Class.forName("com.ozl.day14.Student");
System.out.println(class3.hashCode());
}
}

常见方法

/**
* 反射的常用方法
*/
public class Demo02 {
public static void main(String[] args) throws Exception{
//获取类对象
Class<?> studentClass = Class.forName("com.ozl.day14.Student");
//获取类名字
System.out.println(studentClass.getName());
System.out.println("============");
//获取类的包名
System.out.println(studentClass.getPackage());
System.out.println("============");
//获取类的父类
System.out.println(studentClass.getSuperclass());
System.out.println("============");
//获取类实现的接口
System.out.println(studentClass.getInterfaces());
System.out.println("============");
//获取类的构造器
System.out.println(studentClass.getConstructor());
System.out.println("============");
//无参构造创建实例
Constructor<?> con = studentClass.getConstructor();
Student s1 =(Student)con.newInstance();
System.out.println(s1);
System.out.println("============");
//有参构造创建实例
Constructor<?> con1 = studentClass.getConstructor(Integer.class, String.class);
Student s3 = (Student) con1.newInstance(12,"小李");
System.out.println(s3);
System.out.println("================");
//类对象创建实例
Student s2 = (Student) studentClass.newInstance();
System.out.println(s2);
System.out.println("=============");
//获取类的方法
//1.包含父类继承的方法以及公开的方法
Method[] methods = studentClass.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("===============");
//2.获取类中声明的全部方法,包括私有的方法等,不包含继承方法
Method[] dm = studentClass.getDeclaredMethods();
for (Method method : dm) {
System.out.println(method);
}
//3.获取单个方法
Method run = studentClass.getMethod("run", String.class);
//调用方法
Student student = (Student) studentClass.newInstance();
run.invoke(student, "小明");
//4.获取私有方法
Method jump = studentClass.getDeclaredMethod("jump");
//设置访问权限无效
jump.setAccessible(true);
jump.invoke(student);
//5.获取静态方法
Method eat = studentClass.getMethod("eat");
eat.invoke(null);
System.out.println("==============");
//获取类的属性
//1.获取公开的属性和父类继承的的公开属性
Field[] fields = studentClass.getFields();
System.out.println(fields.length);
//2.获取类对象的声明的方法
Field[] declaredFields = studentClass.getDeclaredFields();
System.out.println(declaredFields.length);
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
//3.获取单个属性
Field name = studentClass.getDeclaredField("name");
//设置访问权限无效
name.setAccessible(true);
//4.属性赋值
Student s = (Student) studentClass.newInstance();
name.set(s,"欧少");//s.name="欧少";
//5.获取值
System.out.println(name.get(s));//s.name
}
}


- 使用反射实现一个调用任何对象方法的通用方法
/**
* 使用反射实现一个调用任何对象方法的通用方法
*/
public class Demo03 {
public static void main(String[] args) throws Exception{
Properties properties = new Properties();
// properties.setProperty("name","lisi");
// System.out.println(properties);
inbvokeAny(properties,"setProperty",new Class[]{String.class,String.class},"name","lisi");
System.out.println(properties);
}
public static Object inbvokeAny(Object obj,String methodName,Class<?>[] types,Object...args)throws Exception{
//创建类对象
Class<?> objClass = obj.getClass();
//获取方法
Method method = objClass.getMethod(methodName,types);
//方法调用
return method.invoke(obj,args);
}
}

设计模式介绍
- 什么设计模式
- 一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结,简单理解:特定问题的特定解决方案
- 好处,实现可重用代码,让代码更容易被他人理解,保证代码可靠性,重用性
- 23种设计模式
工厂设计模式
-
工厂模式主要负责对象创建问题
-
开发中有个非常重要的原则“开闭原则”,对拓展开放,对修改关闭
-
可通过反射进行工厂模式的设计,完成动态的对象创建
-
简单实现工厂模式
测试
public class Demo04 {
public static void main(String[] args) {
System.out.println("=========请选择物品==========");
System.out.println("1.风扇 2.鼠标 3.U盘");
Scanner scanner = new Scanner(System.in);
int choice = scanner.nextInt();
Usb usb = UsbFactory.creatUsb(choice);
if (usb!=null){
System.out.println("购买成功");
usb.service();
}else {
System.out.println("购买失败,无此产品");
}
}
}
UsbFactory
public class UsbFactory {
public static Usb creatUsb(int choice){
Usb usb=null;
if (choice==1){
usb=new Fan();
}else if (choice==2){
usb=new Mouse();
}else if (choice==3)
usb=new Upan();
return usb;
}
}
Usb接口
public interface Usb {
public void service();
}
public class Fan implements Usb{
@Override
public void service() {
System.out.println("风扇开始启动了");
}
}
实现类
public class Mouse implements Usb{
@Override
public void service() {
System.out.println("鼠标开始启动了");
}
}
public class Upan implements Usb{
@Override
public void service() {
System.out.println("U盘开始启动了");
}
}


- 反射优化工厂模式
UsbFactory
public class UsbFactory {
public static Usb creatUsb(String type) {
Usb usb = null;
try {
Class<?> c = Class.forName(type);
usb = (Usb) c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return usb;
}
}
测试
public class Demo04 {
public static void main(String[] args) throws Exception{
System.out.println("=========请选择物品==========");
System.out.println("1.风扇 2.鼠标 3.U盘");
Scanner scanner = new Scanner(System.in);
String choice = scanner.next();
Properties properties = new Properties();
FileInputStream fis = new FileInputStream("src/com/ozl/day14/usb.properties");
properties.load(fis);
fis.close();
Usb usb = UsbFactory.creatUsb(properties.getProperty(choice));
if (usb!=null){
System.out.println("购买成功");
usb.service();
}else {
System.out.println("购买失败,无此产品");
}
}
}
usb.properties
1=com.ozl.day14.Fan
2=com.ozl.day14.Mouse
3=com.ozl.day14.Upan

单例设计模式
- 单例:只允许创建一个该类的对象
- 方式1:饿汉式(类加载时创建,天生线程安全,声明周期长,浪费资源)
测试类
public class Demo05 {
public static void main(String[] args) {
for (int i = 0; i <5 ; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Singleton.getInstance().hashCode());
}
}).start();
}
}
}
Singleton
/**
* 饿汉式单例
* 1.创建一个静态常量
* 2。构造方法私有化,类外部不可创建
* 3.通过一个公开方法,返回这个对象
*/
public class Singleton {
private static final Singleton instance=new Singleton();
private Singleton(){}
public static Singleton getInstance() {
return instance;
}
}

- 方式2:懒汉式(使用时创建,线程不安全,需加同步,声明周期短,节省空间)
同步方法实现
/**
* 懒汉式单例
* * 1.创建一个静态对象
* * 2。构造方法私有化,类外部不可创建
* * 3.通过一个公开方法,返回这个对象
*/
public class Singleton2 {
private static Singleton2 instance=null;
private Singleton2(){}
public static synchronized Singleton2 getInstance() {
if (instance==null){
instance=new Singleton2();
}
return instance;
}
}
同步代码块实现
/**
* 懒汉式单例
* * 1.创建一个静态对象
* * 2。构造方法私有化,类外部不可创建
* * 3.通过一个公开方法,返回这个对象
*/
public class Singleton2 {
private static Singleton2 instance=null;
private Singleton2(){}
public static Singleton2 getInstance() {
synchronized (Singleton2.class){
if (instance==null){
instance=new Singleton2();
}
}
return instance;
}
}
同步代码块优化
/**
* 懒汉式单例
* * 1.创建一个静态对象
* * 2。构造方法私有化,类外部不可创建
* * 3.通过一个公开方法,返回这个对象
*/
public class Singleton2 {
private static Singleton2 instance=null;
private Singleton2(){}
public static Singleton2 getInstance() {
if (instance==null){//提执行效率
synchronized (Singleton2.class){
if (instance==null){
instance=new Singleton2();
}
}
}
return instance;
}
}

- 由于jvm有指令重排序的优化,所以instance=new Singleton2();会分成三部执行
- 给 instance 分配内存
- 调用 Singleton 的构造函数来初始化成员变量
- 将instance对象指向分配的内存空间
- 第二步和第三步有序优化执行顺序可能会不一样,就会出现问题,所以instance 变量声明成 volatile 就可以完美解决
public class Singleton2 {
private volatile static Singleton2 instance=null;
private Singleton2(){}
public static Singleton2 getInstance() {
if (instance==null){//提执行效率
synchronized (Singleton2.class){
if (instance==null){
instance=new Singleton2();
}
}
}
return instance;
}
}
- 方式3: 静态内部类写法 也属于懒汉式(使用时创建,线程安全)
/**
* 单例 静态内部类
*/
public class Singleton3 {
private Singleton3(){};
private static class Holder{
static Singleton3 instance=new Singleton3();
}
public static Singleton3 getInstance(){
return Holder.instance;
}
}
枚举
- 什么是枚举
- 枚举是一个引用类型,枚举是一个规定了取值范围的数据类型
- 枚举变量不能使用其他的数据,只能使用枚举中的常量赋值,提高程序安全性
- 定义枚举使用enum关键字
- 枚举的本质
- 枚举是一个终止类(final 修饰的类),并继承Enum抽象类
- 枚举中的常量就是当前类型的静态常量
/**
* 性别枚举
* 1.枚举必须有枚举常量,也可以包含属性,方法,私有构造方法,构造方法一定是私有方法
* 2.枚举常量必须放在最前面,多个常量之间用逗号隔开,最后的分号可写可不写
*/
public enum Gender {
MALE,FEMALE;
}
public class TestGender {
public static void main(String[] args) {
Gender male = Gender.MALE;
System.out.println(male);
}
}

注解
- 什么是注解
- 注解(Annotation)是代码里的特殊标记,程序可以读取注解,一般用于替代配置文件
- 开发人员可以通过注解告诉类如何运行
- 在java技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么运行类
- 常见注解:@Override,@Deprecated
- 定义注解使用@interface关键字,注解中只能包含属性
- 注解的本质就是接口,继承了Annotation
/**
* 注解使用
*/
public @interface MyAnnotation {
//设置属性(类似方法)
//设置默认值
String name() default "张三";
//不设置默认值
int age();
}
public class Person {
@MyAnnotation(age = 20)
public void show(){
}
}
- 注解属性类型
- String类型
- 基本数据类型
- Class类型
- 枚举类型
- 注解类型
- 以上类型的一维数组
public @interface MyAnnotation2 {
//属性
//字符串类型
String value();
//基本数据类型
int num();
//Class类型
Class<?> class1();
//枚举类型
Gender gender();
//注解类型
MyAnnotation annotation();
//一维数组
char[] char1();
}
- 元注解:用来描述注解的注解
- @Retention:用于指定注解可以保留的域
- RetentionPolicy.Class:注解记录在class文件中,运行Java程序时,JVM不会保留,这是默认值
- RetentionPolicy .RUNTIME:注解记录在class文件中,运行Java程序时,JVM会保留注解,程序可以通过反射获取该注解
- RetentionPolicy.SOURCE:编译时直接丢弃这种策略的注解
- @Target:指定注解用于修饰类的哪个成员上
- 通过反射获取注解信息
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD})//定义声明可以在方法上注解
public @interface PersonInfo {
String name();
int age();
String sex();
}
public class Person {
@MyAnnotation(age = 20)
public void show(){
System.out.println();
}
@PersonInfo(name="小明",age=30,sex="男")
public void show(String name,int age,String sex){
System.out.println(name+"===="+age+"===="+sex);
}
}
public class Demo08 {
public static void main(String[] args) throws Exception{
//获取该类
Class<?> aClass = Class.forName("com.ozl.day14.Person");
//获取方法
Method show = aClass.getMethod("show", String.class, int.class, String.class);
//获取方法上的注解
PersonInfo personInfo = show.getAnnotation(PersonInfo.class);
//打印注解信息
System.out.println(personInfo.name());
System.out.println(personInfo.sex());
System.out.println(personInfo.age());
//调用方法
Person xiaoming = (Person)aClass.newInstance();
show.invoke(xiaoming,personInfo.name(),personInfo.age(),personInfo.sex());
}
}

本文详细介绍了Java反射机制的基本概念及获取类对象的方法,并通过示例展示了反射的应用。此外,还深入探讨了几种常见的设计模式,包括工厂模式、单例模式、枚举和注解的应用。
5万+

被折叠的 条评论
为什么被折叠?



