反射
JDK1.5引入
优点:提高了代码的灵活性,使java语言从静态语言变为半动态语言
创建对象:
先创建类,在类中定义属性,定义方法,使用new关键字创建该类对象
反射使用场景:
1,使用第三方类库时,可以创建其对象,但是不知道对象拥有的属性与方法,此时
就以通过反射进行获取
2,使用三方类库,只知道类名,但是不知道类中有什么,可以使用反射进行获取与使用 3,使用三方类库,只知道类所在的包名与类名,但是操作.可以使用反射对其进行操作
类对象
概念
一个类被JVM加载时,会生成一个类对象 类对象中包含了该类的属性,方法,构造函数,父类,父接口等信息
注意: 一个类只会被JVM加载一次,所以一个类的类对象只有一个
通过new关键字创建出来的对象,称为类的对象,又名实例对象.与类对象不是一个东西
获取类对象的方式
方式1:
通过实例对象,getClass()方法获取
Student stu = new Student();//
Class class1 = stu.getClass();//通过实例对象获取
方式2:
通过类名获取类的对象
类名.class
Class class2 = Student.class;//使用类名获取
方式3:
通过Class类提供的静态方法获取
Class.forName("包名,类名");
Class class3 = Class.forName("dome01.Student");//使用类名与包名获取
System.out.println(class1);//打印下
System.out.println(class2);
System.out.println(class3);
类对象的常用方法
概述:获取该类的信息
1. 获取类的全名称(包名+类名) String getName()
获取类名 String getSimpleName();
System.out.println(class1.getName());//获取类全名
System.out.println(class1.getSimpleName());//获取类名
获取类加载器 ClassLoader getClassLoader();
ClassLoader loader = class1.getClassLoader();//获取类加载器
类加载器负责在运行时将 Java 类动态加载到 JVM (Java 虚拟机)。它们也是 JRE(Java 运行时环境)的一部分。因此,借助类加载器,JVM 无需了解底层文件或文件系统即可运行 Java 程序。
此外,这些 Java 类不会一次全部加载到内存中,而是在应用程序需要它们时才会进行加载。这就是类加载器发挥作用的地方,他们负责将类加载到内存中。
2. 获取父类 Class getSuperclass();
Class superclass = class1.getSuperclass();//获取父类
获取父接口 Class[] getInterfaces();
Class[] interfaces = class1.getInterfaces();//获取父类接口
for (Class classtese : interfaces) {
}
由于接口可能有多个,所有需要数组存储
3. 获取包 Package getPackage();
方法: getName()获取包名
Package package1 = class1.getPackage();//获取包
package1.getName();//获取包名
4. 通过类对象创建类的实例对象
Object newInstance();
注意1:如果该类中没有无参构造函数,那么此时方法将出现NoSuchMethodException异常 注意2:如果该类的无参构造访问权限不足,此时方法将出现IllegalAccessException异常 获取属性
Object newInstance = class1.newInstance();//通过类对象创建实例
Student student2 = (Student)newInstance;//需要强转
5.
获取类的所有公共属性
注意:可以获取到父类的公共属性
Field[] getFields();
Field[] fields = class1.getFields();//获取父类的公共属性
获取本类的所有属性(包括私有属性)
注意:只能获取本类的所有属性
Field[] getDeclaredFields();
Field[] declaredFields = class1.getDeclaredFields();//获取本类属性
获取指定的属性
Field getDeclaredField("属性名");
Field declaredField = class1.getDeclaredField("age");//获取指定属性
6.获取构造函数
获取类的所有公共构造函数
Constructor[] getConstructors();
Constructor[] constructors = class1.getConstructors();//获取所有公共构造函数
获取类的所有构造函数
Constructor getDeclaredConstructors();
Constructor[] declaredConstructors = class1.getDeclaredConstructors();//获取该类所有的构造函数
获取类的指定构造函数
Constructor getDeclaredConstructor(获取构造函数的参数列表的类对象列表);
Constructor<? extends Student> declared2 = class1.getDeclaredConstructor(String.class, int.class);//获得有参构造,根据传入参数的个数,获取到的构造函数也不同
Student student3 = declared2.newInstance("3",12);//使用构造函数创建对象
Constructor<? extends Student> declared3 = class1.getDeclaredConstructor( int.class);
declared3.setAccessible(true);
Student student3 = declared3.newInstance(6);
当构造函数被私有修饰时,可以用setAccessible(true);方法绕过后创建
7.获取方法
获取类中所有公共方法
Method[] getMethods();
注意:可以获取到父类提供的公共方法(不包含私有)
Method[] methods = class1.getMethods();//获取所有的公共类方法,可以获取到父类的公共方法
获取类中所有方法
Method[] getDeclaredMethods();
注意:只能获取该类的所有方法
Method[] methods = class1.getMethods();//获取所有的公共类方法,可以获取到父类的公共方法
Method[] methods2 = class1.getDeclaredMethods();
for (Method method : methods2) {
System.out.println(method);
}
没有构造方法

获取类中指定方法
Method invoke(String name, Class... p)
参数1:方法名
参数2:该方法形参列表对应的类对象列表
如:获取下eat方法,setAge方法
mo1.invoke(student);//执行方法,参数为对象名,方法的参数
mo2.invoke(method2, 23);//
m01.setAccessible(true);
同样的,可以绕过权限修饰符
Field类
常用方法:
修改对象的属性值
void set(对象, 修改后的值)
获取对象的属性值
Object get(对象);
略过访问权限修饰符
void setAccessible(true);
获取属性名
String getName();
Constructor类
常用方法:
创建对象
T newInstance(实参列表)
Constructor<? extends Student> declared3 = class1.getDeclaredConstructor( int.class);
declared3.setAccessible(true);
Student student3 = declared3.newInstance(6);
略过访问权限修饰符
void setAccessible(true);
Method类
常用方法:
作用:执行方法
Object invoke(Object obj, Object... args)
参数:
obj:执行该方法的对象
args:实参列表
返回值:
执行的方法的返回值
mo1.invoke(student);//执行方法,参数为对象名,方法的参数
mo2.invoke(method2, 23);//
略过访问权限修饰符
void setAccessible(true);
m01.setAccessible(true);
同样的,可以绕过权限修饰符
设计模式
一套被反复使用,多数人知道,经过分类,代码设计经验的总结 简单的理解为:设计模式就是解决固定问题的方案
设计模式规则
单一职责:一个方法或接口或类..只干一件事
开闭原则:对扩展开放,对修改关闭
里式替换:子类可以扩展父类的功能,但不能改变父类原有的功能。
依赖倒置:对抽象进行编程,不要对实现进行编程,这样就降低了程序与实现模块间的耦合
接口隔离:使用多个专门的接口比使用单个接口要好很多。
迪米特法则:一个类对于其他类知道的越少越好
单例模式
解决问题:一个只产生一个对象的类
分类:
饿汉式
步骤: 1,私有构造函数,此时外部就无法通过new调用构造函数创建对象
2,在该类中提供一个私有的静态的不可修改的该类对象
3,提供公共静态方法,该方法返回步骤2的对象
以后需要外部需要该类对象只能使用类名.步骤3提供的静态方法得到
优点:线程安全
缺点:浪费内存,在类加载时就会创建对象
public class YuanBao {
private static final YuanBao yb=new YuanBao();
private void YuanBao(){
}
public static YuanBao getInstance() {
return yb;
}
}
懒汉式 线程不安全
步骤: 1,私有构造函数
2,在该类中声明一个静态该类对象
3,提供公共静态方法,方法中 判断步骤2的对象是否为空
.如果为空创建对象,赋值给该属性.在返回该类对象.如果
不为空直接返回
优点:不浪费内存
缺点:只能应用与单线程情况下
public class YuanBao {
private static YuanBao yb;
private void YuanBao(){
}
public static YuanBao getInstance() {
if(yb==null) {
yb=new YuanBao();
}
return yb;
}
}
优化:可在基础上加上锁,但是会影响效率,多个线程使用会降低速度
优化:静态内部类实现懒汉式
public class YuanBao {
private void YuanBao(){
}
public static YuanBao getInstance() {
return Yuzhe.YUAN_BAO;
}
private static class Yuzhe{
public static final YuanBao YUAN_BAO = new YuanBao();
//内部类不加载就不会创建,私有的也不会导包
}
}
工厂模式
解决问题:对于类似的事物, 一个方法只能使用一种对象,
如:不同的动物,狗和猫需要使用同一种方法,如果一种动物使用一种方法,就会显得繁琐。
package work3;
abstract class Animal {
String name;
public Animal() {
super();
}
public Animal(String name) {
super();
this.name = name;
}
void enjoy() {};
}
package work3;
public class Cat extends Animal{
private String eyesColor;
public Cat() {
super();
}
public Cat(String name,String eyesColor) {
super(name);
this.eyesColor=eyesColor;
}
public String getEyesColor() {
return eyesColor;
}
public void setEyesColor(String eyesColor) {
this.eyesColor = eyesColor;
}
public void enjoy() {
System.out.println( name+"猫开心笑");
}
}
package work3;
public class Dog extends Animal{
private String furColor;
public Dog() {
super();
}
public Dog(String name,String fuString) {
super(name);
}
public String getFurColor() {
return furColor;
}
public void setFurColor(String furColor) {
this.furColor = furColor;
}
public void enjoy() {
System.out.println( name+"狗开心叫");
}
}
package work3;
public class Lady {
private String name;
private Animal pet;
public Lady() {
super();
}
public Lady(String name, Animal pet) {
super();
this.name = name;
this.pet = pet;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Animal getPet() {
return pet;
}
public void setPet(Animal pet) {
this.pet = pet;
}
public void myPetEnjoy(Animal pet) {
System.out.println(name+"逗"+pet.name);
if(pet instanceof Dog) {
Dog dog=(Dog)pet;//在方法这需要判断
dog.enjoy();
}
if(pet instanceof Cat) {
Cat cat=(Cat)pet;
cat.enjoy();
}
}
}
package work3;
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("汤姆","蓝");
Dog dog = new Dog("斯派克","灰");
Lady lady = new Lady("张女士",cat);
Lady lady2 = new Lady("张女士",dog);
lady.myPetEnjoy(cat);
System.out.println();
lady2.myPetEnjoy(dog);
}
}
消费者模式
线程那块写了
监听者模式(等待补充)
枚举
作用:限定值的取值范围
注意:
枚举是一种引用数据类型
枚举变量的值必须是枚举常量
枚举中可以定义普通的属性,方法与私有的构造函数
如果枚举中只有枚举常量,此时可以忽略分号不写.多个枚举常量直接使用逗号隔开
如果枚举中定义了普通属性等,此时枚举常量最后需要使用分号
枚举的定义:
访问权限修饰符 enum 枚举名{
枚举常量名1,枚举常量名2,...
}
枚举的使用:
声明变量
作为形参
public enum Myenum {
ZHUOZI,YIZI,YIGUI;//里面也不会创建对象
private String nameS;
public void test() {
}
private Myenum() {
}
}
package dome02;
public class JJGongChang {
public static JiaJu getBean(Myenum myMenu) {
if (myMenu == Myenum.ZHUOZI) {
return new ZhuoZi();
}else if(myMenu == Myenum.YIGUI) {
return new YiZi();
}
return null;
}
}
abstract class JiaJu{
}
class ZhuoZi extends JiaJu{
}
class YiZi extends JiaJu{
}
这样传参就只能使用枚举里面的名称
本文主要介绍Java的反射和设计模式。反射自JDK1.5引入,提高了代码灵活性,可用于操作第三方类库。文中介绍了类对象概念、获取方式及常用方法,还阐述了设计模式规则,包括单例、工厂、消费者等模式,最后提及枚举的作用、定义和使用。
881

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



