java基础九 反射和匿名内部类

反射是框架设计的灵魂
(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))

一、反射的概述

class是一切反射的根源,JAVA反射机制是在运行状态中,对于任和一个类,通过反射都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
本人简单理解就是用一段字符串直接调取类及其该类的方法。

反射的作用

通过反射访问java对象的属性,方法,构造方法等

反射机制的相关类

与Java反射相关的类如下:

类名用途
Class类代表类的实体,在运行的Java应用程序中表示类和接口
Field类代表类的成员变量(成员变量也称为类的属性)
Method类代表类的方法
Constructor类代表类的构造方法

注意:都是Object类的子类

反射的基本机制

: 可以根据一个“类全名字符串” ,获得代表这个类的class对象,然后根据这个class对象构造出这个类的真正实例对象
可用Class.forName(“类的包名”)这个方法得到一个Class类

String className = "cn.edu360.javase24.reflect.demo.SerivceOne";  // 通常这个字符串常常存在文件当中,用io流调用
Class<?> forName = Class.forName(className);   // 根据类名字符串“SerivceOne”获取class对象
SerivceOne o = (SerivceOne)forName.newInstance();  // 用class对象构造出这个类SerivceOne的实例对象
o.say();

然后该反射常常应用于接口
比如这里我们有一个接口Fuck还有其 实现类FuckImpl,然后约定好将该实现类的完整包名保存入文件当中。
然后我们调用该接口的时候就可以这样

public class Menu {
	
public static void main(String[] args) throws Exception {

	// 从约定的文件中读取所需类的实现类全名
	BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("f:/a.txt")));
	String ClassName = br.readLine();   /将文件中的按行包名输出
	
	Class<?> forName = Class.forName(ClassName); // forName代表的是serviceClassName字符串所指定的类的类class模板
	
	// 根据类全名构造这个service实现类的实例
	Fuck fuck = (Fuck) forName.newInstance();`}}

三、通过反射获取类的构造方法、方法以及属性

Class<?> forName = Class.forName(ClassName);
	
	// 根据类全名构造这个service实现类的实例
	Fuck fuck = (Fuck) forName.newInstance();`
	//methodName存的是方法名的字符串,从forName这个class模板中获取到指定的方法
	Method method=forName.getMethod(methodName) ;
	//让Method在对象上执行,()中写对象和参数
	Object invoke=method.invoke(fuck,12);

-------------------------------------------------------------------------
//如果存在同名方法,则有参数的需要这样输入
   	Method method2=forName.getMethod(methodName,String.Class) ;
   	Object invoke=method.invoke(fuck,12);

配置文件用到的小工具Properties()

Properties中的主要方法

(1)load(InputStream inStream)

这个方法可以从.properties属性文件对应的文件输入流中,加载属性列表到Properties类对象。如下面的代码:

Properties pro = new Properties();
FileInputStream in = new FileInputStream("a.properties");
pro.load(in);
in.close();

(2)store(OutputStream out, String comments)

这个方法将Properties类对象的属性列表保存到输出流中。如下面的代码:

FileOutputStream oFile = new FileOutputStream(file, "a.properties");
pro.store(oFile, "Comment");
oFile.close();

如果comments不为空,保存后的属性文件第一行会是#comments,表示注释信息;如果为空则没有注释信息。

注释信息后面是属性文件的当前保存时间信息。

(3)getProperty/setProperty

这两个方法是分别是获取和设置属性信息。

反射与属性配置文件的加载

Properties props = new Properties();
//加载xx.properties属性配置文件
props.load(Test.class.getClassLoader().getResourceAsStream("xx.properties"));
//取配置参数
String value = props.getProperty("key");
	
	Class<?> forName = Class.forName(value); // forName代表的是serviceClassName字符串所指定的类的类class模板
	
	// 根据类全名构造这个service实现类的实例
	Fuck fuck = (Fuck) forName.newInstance();`

然后应该在同个包中直接建立***file***
内容是
key=value的形式

ClassName=fuckMan
Method=fuck

匿名内部类

匿名内部类也就是没有名字的内部类

正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写

但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
实例1:不使用匿名内部类来实现抽象方法

abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

运行结果:eat something

可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用

但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?

这个时候就引入了匿名内部类

实例1:不使用匿名内部类来实现抽象方法

abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

运行结果:eat something
可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用

但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?

这个时候就引入了匿名内部类
实例2:匿名内部类的基本实现

abstract class Person {
    public abstract void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了

这样便可以省略一个类的书写

并且,匿名内部类还能用于接口上

实例3:在接口上使用匿名内部类

interface Person {
    public void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

运行结果:eat something

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值