更多资源和微信公众号[Java帮助](不是微信朋友的公众号)和[Java帮助] QQ空间、技术文章、视频、面试资料。
欢迎关注!
学习交流请加【Java帮帮】自学交流QQ群553841695
1:反射(理解)
(1)类的加载及类加载器
类的加载:
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
加载
就是指将class文件读入内存,并为之创建一个Class对象。
任何类被使用时系统都会建立一个Class对象。
连接
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
初始化 就是我们以前讲过的初始化步骤
类初始化时机:
创建类的实例
访问类的静态变量,或者为静态变量赋值
调用类的静态方法
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
初始化某个类的子类
直接使用java.exe命令来运行某个主类
类加载器:
负责将.class文件加载到内在中,并为之生成对应的Class对象。
虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行。
类加载器的组成
Bootstrap ClassLoader 根类加载器
Extension ClassLoader 扩展类加载器
Sysetm ClassLoader 系统类加载器
类加载器作用:
Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
(2)反射:
通过字节码文件对象,去使用成员变量,构造方法,成员方法
package cn.itcast_01;
public class Person {
private String name;
int age;
public String address;
public Person() {
}
private Person(String name) {
= name;
}
Person(String name, int age) {
= name;
= age;
}
public Person(String name, int age, String address) {
= name;
= age;
= address;
}
public void show() {
Sy("show");
}
public void method(String s) {
Sy("method " + s);
}
public String getString(String s, int i) {
return s + "—" + i;
}
private void function() {
Sy("function");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}
}
package cn.itcast_01;
/*
* 反射:就是通过class文件对象,去使用该文件中的成员变量,构造方法,成员方法。
*
* Person p = new Person();
* p.使用
*
* 要想这样使用,首先你必须得到class文件对象,其实也就是得到Class类的对象。
* Class类:
* 成员变量Field
* 构造方法Constructor
* 成员方法Method
*
* 获取class文件对象的方式:
* A:Object类的getClass()方法
* B:数据类型的静态属性class
* C:Class类中的静态方法
* public static Class forName(String className)
*
* 一般我们到底使用谁呢?
* A:自己玩任选一种,第二种比较方便
* B:开发第三种
* 为什么呢?因为第三种是一个字符串,而不是一个具体的类名。这样我们就可以把这样的字符串配置到配置文件中。
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1
Person p = new Person();
Class c = p.getClass();
Person p2 = new Person();
Class c2 = ();
Sy(p == p2);// false
Sy(c == c2);// true
// 方式2
Class c3 = Per;
// int.class;
// S;
Sy(c == c3);
// 方式3
// ClassNotFoundException
Class c4 = Cla("cn.i;);
Sy(c == c4);
}
}
(3)反射的使用
A:通过反射获取构造方法并使用
package cn.itcast_02;(1)
import java.lang.re;
import cn.i;
/*
* 通过反射获取构造方法并使用。
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Cla("cn.i;);
// 获取构造方法
// public Constructor[] getConstructors():所有公共构造方法
// public Constructor[] getDeclaredConstructors():所有构造方法
// Constructor[] cons = c.getDeclaredConstructors();
// for (Constructor con : cons) {
// Sy(con);
// }
// 获取单个构造方法
// public Constructor<T> getConstructor(Class<?>… parameterTypes)
// 参数表示的是:你要获取的构造方法的构造参数个数及数据类型的class字节码文件对象
Constructor con = c.getConstructor();// 返回的是构造方法对象
// Person p = new Person();
// Sy(p);
// public T newInstance(Object… initargs)
// 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
Object obj = con.newInstance();
Sy(obj);
// Person p = (Person)obj;
// p.show();
}
}
package cn.itcast_02;(2)
import java.lang.re;
/*
* 需求:通过反射去获取该构造方法并使用:
* public Person(String name, int age, String address)
*
* Person p = new Person("林青霞",27,"北京");
* Sy(p);
*/
public class ReflectDemo2 {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Cla("cn.i;);
// 获取带参构造方法对象
// public Constructor<T> getConstructor(Class<?>… parameterTypes)
Constructor con = c.getConstructor(S, int.class,
S);
// 通过带参构造方法对象创建对象
// public T newInstance(Object… initargs)
Object obj = con.newInstance("林青霞", 27, "北京");
Sy(obj);
}
}
package cn.itcast_02;(3)
import java.lang.re;
/*
* 需求:通过反射获取私有构造方法并使用
* private Person(String name){}
*
* Person p = new Person("风清扬");
* Sy(p);
*/
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Cla("cn.i;);
// 获取私有构造方法对象
// NoSuchMethodException:每个这个方法异常
// 原因是一开始我们使用的方法只能获取公共的,下面这种方式就可以了。
Constructor con = c.getDeclaredConstructor(S);
// 用该私有构造方法创建对象
// IllegalAccessException:非法的访问异常。
// 暴力访问
con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查。
Object obj = con.newInstance("风清扬");
Sy(obj);
}
}
B:通过反射获取成员变量并使用
package cn.itcast_03;
import java.lang.re;
import java.lang.re;
/*
* 通过发生获取成员变量并使用
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Cla("cn.i;);
// 获取所有的成员变量
// Field[] fields = c.getFields();
// Field[] fields = c.getDeclaredFields();
// for (Field field : fields) {
// Sy(field);
// }
/*
* Person p = new Person(); p.address = "北京"; Sy(p);
*/
// 通过无参构造方法创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
Sy(obj);
// 获取单个的成员变量
// 获取address并对其赋值
Field addressField = c.getField("address");
// public void set(Object obj,Object value)
// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
addre(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
Sy(obj);
// 获取name并对其赋值
// NoSuchFieldException
Field nameField = c.getDeclaredField("name");
// IllegalAccessException
nameField.setAccessible(true);
nameField.set(obj, "林青霞");
Sy(obj);
// 获取age并对其赋值
Field ageField = c.getDeclaredField("age");
ageField.setAccessible(true);
ageField.set(obj, 27);
Sy(obj);
}
}
C:通过反射获取成员方法并使用
package cn.itcast_04;
import java.lang.re;
import java.lang.re;
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Cla("cn.i;);
// 获取所有的方法
// Method[] methods = c.getMethods(); // 获取自己的包括父亲的公共方法
// Method[] methods = c.getDeclaredMethods(); // 获取自己的所有的方法
// for (Method method : methods) {
// Sy(method);
// }
Constructor con = c.getConstructor();
Object obj = con.newInstance();
/*
* Person p = new Person(); p.show();
*/
// 获取单个方法并使用
// public void show()
// public Method getMethod(String name,Class<?>… parameterTypes)
// 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
Method m1 = c.getMethod("show");
// obj.m1(); // 错误
// public Object invoke(Object obj,Object… args)
// 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
m1.invoke(obj); // 调用obj对象的m1方法
Sy("———-");
// public void method(String s)
Method m2 = c.getMethod("method", S);
m2.invoke(obj, "hello");
Sy("———-");
// public String getString(String s, int i)
Method m3 = c.getMethod("getString", S, int.class);
Object objString = m3.invoke(obj, "hello", 100);
Sy(objString);
// String s = (String(obj, "hello",100);
// Sy(s);
Sy("———-");
// private void function()
Method m4 = c.getDeclaredMethod("function");
m4.setAccessible(true);
m4.invoke(obj);
}
}
(4)反射案例
A:通过反射运行配置文件的内容
B:通过反射越过泛型检查
C:通过反射给任意的一个对象的任意的属性赋值为指定的值
(5)动态代理
动态代理:
代理:本来应该自己做的事情,却请了别人来做,被请的人就是代理对象。
举例:春季回家买票让人代买
动态代理:在程序运行过程中产生的这个对象
而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib
Proxy类中的方法创建动态代理类对象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
最终会调用InvocationHandler的方法
InvocationHandler
Object invoke(Object proxy,Method method,Object[] args)
2:设计模式
(1)装饰设计模式
装饰设计模式概述
装饰模式就是使用被装饰类的一个子类的实例,在客户端将这个子类的实例交给装饰类。是继承的替代方案
优点
使用装饰模式,可以提供比继承更灵活的扩展对象的功能,它可以动态的添加对象的功能,并且可以随意的组合这些功能
缺点
正因为可以随意组合,所以就可能出现一些不合理的逻辑
BufferedReader br = new BufferedReader(new InputStreamReader));
Scanner sc = new Scanner);
package cn.itcast_02;
public interface Phone {
public abstract void call();
}
package cn.itcast_02;
public class IPhone implements Phone {
@Override
public void call() {
Sy("手机可以打电话了");
}
}
package cn.itcast_02;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.u;
public class PhoneDemo {
public static void main(String[] args) {
Phone p = new IPhone();
p.call();
Sy("————");
// 需求:我想在接电话前,听彩铃
PhoneDecorate pd = new RingPhoneDecorate(p);
();
Sy("————");
// 需求:我想在接电话后,听音乐
pd = new MusicPhoneDecorate(p);
();
Sy("————");
// 需求:我要想手机在接前听彩铃,接后听音乐
// 自己提供装饰类,在打电话前听彩铃,打电话后听音乐
pd = new RingPhoneDecorate(new MusicPhoneDecorate(p));
();
Sy("———-");
// 想想我们在IO流中的使用
// InputStream is = Sy;
// InputStreamReader isr = new InputStreamReader(is);
// BufferedReader br = new BufferedReader(isr);
BufferedReader br = new BufferedReader(new InputStreamReader));
BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(
Sy)));
Scanner sc = new Scanner);
}
}
package cn.itcast_02;
public abstract class PhoneDecorate implements Phone {
private Phone p;
public PhoneDecorate(Phone p) {
= p;
}
@Override
public void call() {
.call();
}
}
package cn.itcast_02;
public class RingPhoneDecorate extends PhoneDecorate {
public RingPhoneDecorate(Phone p) {
super(p);
}
@Override
public void call() {
Sy("手机可以听彩铃");
();
}
}
package cn.itcast_02;
public class MusicPhoneDecorate extends PhoneDecorate {
public MusicPhoneDecorate(Phone p) {
super(p);
}
@Override
public void call() {
();
Sy("手机可以听音乐");
}
}
(2)模版设计模式
模版设计模式概述
模版方法模式就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现
优点
使用模版方法模式,在定义算法骨架的同时,可以很灵活的实现具体的算法,满足用户灵活多变的需求
缺点
如果算法骨架有修改的话,则需要修改抽象类
package cn.itcast_01;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public abstract class GetTime {
// 需求:请给我计算出一段代码的运行时间
public long getTime() {
long start = Sy();
// for循环
// for (int x = 0; x < 10000; x++) {
// Sy(x);
// }
// 视频
// try {
// BufferedInputStream bis = new BufferedInputStream(
// new FileInputStream("a.avi"));
// BufferedOutputStream bos = new BufferedOutputStream(
// new FileOutputStream("b.avi"));
// byte[] bys = new byte[1024];
// int len = 0;
// while ((len = bis.read(bys)) != -1) {
// bos.write(bys, 0, len);
// }
// bos.close();
// bis.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// 再给我测试一个代码:集合操作的,多线程操作,常用API操作的等等…
code();
long end = Sy();
return end – start;
}
public abstract void code();
}
package cn.itcast_01;
public class GetTimeDemo {
public static void main(String[] args) {
// GetTime gt = new GetTime();
// Sy() + "毫秒");
GetTime gt = new ForDemo();
Sy() + "毫秒");
gt = new IODemo();
Sy() + "毫秒");
}
}
package cn.itcast_01;
public class ForDemo extends GetTime {
@Override
public void code() {
for (int x = 0; x < 100000; x++) {
Sy(x);
}
}
}
package cn.itcast_01;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IODemo extends GetTime{
@Override
public void code() {
try {
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream("a.avi"));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("b.avi"));
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
bos.close();
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3:JDK新特性
(1)JDK5(掌握)
装箱和拆箱
泛型
增强for
静态导入
可变参数
枚举
枚举概述
是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内。举例:一周只有7天,一年只有12个月等。
回想单例设计模式:单例类是一个类只有一个实例
那么多例类就是一个类有多个实例,但不是无限个数的实例,而是有限个数的实例。这才能是枚举类。
通过自己定义一个枚举类来演示案例
第一版
第二版
第三版
发现自己定义一个枚举类,比较麻烦,所以,java就提供了枚举类供我们使用。
格式是:只有枚举项的枚举类
public enum 枚举类名 {
枚举项1,枚举项2,枚举项3…;
}
int compareTo(E o)
String name()
int ordinal()
String toString()
<T> T valueOf(Class<T> type,String name)
values()
此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便
(2)JDK6(了解)
(3)JDK7(理解)
(1)二进制的表现形式:
JDK7开始,终于可以用二进制来表示整数(byte,short,int和long)。使用二进制字面量的好处是,可以使代码更容易被理解。语法非常简单,只要在二进制数值前面加 0b或者0B
举例:
int x = ob110110
(2)用_分隔数据:
为了增强对数值的阅读性,如我们经常把数据用逗号分隔一样。JDK7提供了_对数据分隔。
举例:
int x = 100_1000;
注意事项:
不能出现在进制标识和数值之间
不能出现在数值开头和结尾
不能出现在小数点旁边
(3)switch语句可是用字符串
switch 语句可以用字符串
(4)泛型推断(菱形泛型)
(5)多catch的使用
异常的多个catch合并
格式:
try(必须是java.lang.AutoCloseable的子类对象){…}
好处:
资源自动释放,不需要close()了
把需要关闭资源的部分都定义在这里就ok了
主要是流体系的对象是这个接口的子类(看JDK7的API)
(6)自动释放资源的用法
(4)JDK8(了解)
可以去网上了解资料
获取更多资源加微信公众号【Java帮帮】 (是公众号,不是微信好友哦)
还有【Java帮帮】QQ空间,技术文章,视频,面试资料。欢迎关注!
学习交流请加【Java帮帮】自学交流QQ群553841695
1.文章《类加载器和反射有什么关系》援引自互联网,为网友投稿收集整理,仅供学习和研究使用,内容仅代表作者本人观点,与本网站无关,侵删请点击页脚联系方式。
2.文章《类加载器和反射有什么关系》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
相关推荐
- . 现代买票为什么带上携程保险
- . 潮阳怎么去广州南站
- . 湖南马拉河怎么样
- . 烧纸为什么到三岔路口
- . 百色为什么这么热
- . 神州租车怎么样
- . 芜湖方特哪个适合儿童
- . 护肤品保养液是什么类目
- . 早晚的护肤保养有哪些项目
- . 女孩护肤品怎么保养的最好