目录
语言基础
先说结论Java是一门跨平台,混合型的语言。因为所有程序的运行都要分为这么三个步骤
1.程序员编写代码脚本。像c语言写完后会有个helloworld.c文件,python有个hello.py文件,java会有一个hello.java文件 。
2对编写好的语言进行编译或者说翻译变成二进制内容,因为计算机只认识0-1。
3.将二进制内容进行执行运行。
在这里针对第二步的不同将语言进行了分类分别是编译型,解释性和混合型,java就是混合型。
编译型
典型的就是c语言了,会先对 .c 文件进行一次编译,然后生成一个obj文件然后运行,因为编译不同操作系统,不同设备硬件可能存在差异,所以.c 文件需要每次都编译一次。
解释型
典型的就是python了,它写完代码后不会再生成多余的文件,而是直接按行就解释了,所以说python的代码就直接是源码了。
混合型
顾名思义就是既有编译又有解释,最典型的就是java了,在写完一个.java文件后需要先编译生成一个.class的二进制字节码文件,然后再按行对这个class字节码文件进行按行的解释,并且解释的平台是jvm,因此而具有很好的跨平台性。这里要再次强调一下java 是会在编译成class文件后还会逐行进行解释运行
反射
反射就是程序在运行的过程中,能知道类的属性和方法,能调用对象的属性和方法。并且利用反射 创建的对象可以无视修饰符调用类里面的内容
反射都是要从class字节码文件中获取的内容。
-
如何获取class字节码文件的对象
-
利用反射如何获取构造方法(创建对象)
-
利用反射如何获取成员变量(赋值,获取值)
-
利用反射如何获取成员方法(运行)
获取class字节码文件对象
一共有如下3种方法
-
Class这个类里面的静态方法forName("全类名")(最常用)
- Class clazz1 = Class.forName("com.itheima.reflectdemo.Student");
-
通过具体类的class属性获取
- Class clazz2 = Student.class;
-
通过对象获取字节码文件对象的getClass()方法
- Class clazz3 = s.getClass();
获取构造方法(创建对象)
假设clazz是Student这个类的 字节码文件对象
1.获取空参的构造方法
Constructor con = clazz.getConstructor();
2.利用空参构造方法创建对象
Student stu = (Student) con.newInstance();
获取成员变量(赋值,获取值)
假设clazz是Student这个类的 字节码文件对象,s是具体的Student类的一个具体的对象
获取类属性--name
Field field = clazz.getDeclaredField("name");
临时修饰name的访问权限
field.setAccessible(true);
设置(修改)name的值
field.set(s,"wangwu");
表示我要获取这个对象的name的值,获取name的值,查看验证
String result = (String)field.get(s);
获取成员方法(运行)
假设clazz是Student这个类的 字节码文件对象,s是具体的Student类的一个具体的对象
获取一个指定的方法
Method eatMethod = clazz.getMethod("eat",String.class);
运行
String result = (String) eatMethod.invoke(s, "重庆小面");
动态代理
动态代理三要素:
真正干活的对象
代理对象
利用代理调用方法
动态代理简单的理解就是通过反射,去运行某个类的某个的具体对象的方法。因此动态代理可以,无侵入式的给方法增强功能 ,另外代理可以增强或者拦截的方法都在接口中,接口需要写在newProxyInstance的第二个参数里。java专门为这种动态代理提供了一个类newProxyInstance。
代理类
1.先自定义一个代理类名字是ProxyUtil
2.定义名创建需要被代理的类对象,也就是代理经纪人这里是Star star = (Star)Proxy.newProxyInstance(xxx)
2.1继续补充newProxyInstance里面的参数,第一个参数是ProxyUtil.class.getClassLoader(),是固定的,是一个类加载器,可以理解为准备开始逐行解释class文件了
2.2第二个参数要指定接口,new Class\[\]{Star.class},这些接口用于指定生成的代理要实现哪些方法这里是"唱歌","跳舞"方法
2.3第三个参数也是最麻烦的new InvocationHandler() {xxx}进行真正的代理运行要实现的方法要新建一个InvocationHandler类对象(接口)然后再对象的方法里面用反射实现调用
2.3.1这里是具体的方法实现{public Object invoke(Object proxy, Method method, Object\[\] args)} ,返回Object,这里invoke不能用其他的名字,因为这个是抽象方法必须要实现。然后这里的第一个参数是就是被代理的对象,第二个是被代理对象要调用的方法,第三个是方法的传入值。
java
//类
public class ProxyUtil {
public static Star createProxy(BigStar bigStar){
Star star = (Star) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(),
new Class[]{Star.class},
new InvocationHandler(){
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
if("sing".equals(method.getName())){
System.out.println("准备话筒,收钱");
}else if("dance".equals(method.getName())){
System.out.println("准备场地,收钱");
}
//去找大明星开始唱歌或者跳舞
//代码的表现形式:调用大明星里面唱歌或者跳舞的方法
return method.invoke(bigStar,args);
}
}
);
return star;
}
}
主程序
1.创建对象BigStar bigStar = new BigStar("鸡哥");
2.创建代理对象Star proxy = ProxyUtil.createProxy(bigStar);
3.调用代理
String result = proxy.sing("只因你太美");
System.out.println(result);
ps:接口类
java
public interface Star {
//我们可以把所有想要被代理的方法定义在接口当中
//唱歌
public abstract String sing(String name);
//跳舞
public abstract void dance();
}