java执行过程
类加载机制
生产者消费者模型
描述:为避免因数据共享带来的错误,常使用互斥,关键字(synchronized)机制对共享资源的同步访问。
- 在Java中提供了wait-notify(等待唤醒)机制,通过该机制可以实现线程间的通信协作。
- Java提供了一个精心设计的线程间通信机制即wait-notify机制,通过该机制可以实现线程协作。
- wait-notify机制是通过使用wait()、notify()和notifyAll()三个方法来实现的。这三个方法均定义在Object类中,是final修饰的实例方法。
这三个方法必须在synchronized代码中调用,而且只有通过锁对象才能调用这三个方法。 - wait()方法
通过当前同步锁调用该方法的线程在当前同步锁下进入等待状态,直到其他线程通过相同的同步锁调用notify( )或者notifyAll()方法。 - notify( )
通过当前同步锁调用该方法,唤醒在当前同步锁下等待的线程中的一个结束等待。 - notifyAll()
通过当前同步锁调用该方法,唤醒在当前同步锁下等待的所有线程结束等待。
//面包柜
public class Cupboard {
private int count;//面包数量
private int size;//面包容量
public Cupboard(int size ){
this.size=size;
}
//放入一个面包,该方法是同步方法,同步锁为this
public synchronized void add(){
while(this.isFull()) {
System.out.println(Thread.currentThread().getName()+":柜内面包数:"+count+",已满!等待中......");
try {
this.wait();//在当前同步锁对象(this)下等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
System.out.println(Thread.currentThread().getName()+":放入一个面包,柜内面包数:"+count);
this.notifyAll();//唤醒在当前同步锁对象(this)下等待的所有线程
//Thread.yield();//让步,给其它线程以运行机会
}
//取出一个面包,该方法是同步方法,同步锁为this
public synchronized void remove(){
while(this.isEmpty()) {
System.out.println(Thread.currentThread().getName()+":柜内面包数:"+count+",已空!等待中......");
try {
this.wait();//在当前同步锁对象(this)下等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println(Thread.currentThread().getName()+":取出一个面包,柜内面包数:"+count);
this.notifyAll();//唤醒在当前同步锁对象(this)下等待的所有线程
//Thread.yield();//让步,给其它线程以运行机会
}
//面包柜是否为空
public boolean isEmpty(){
return count<1;
}
//面包柜是否已满
public boolean isFull(){
return count>=size;
}
}
public class Test {
public static void main(String[] args) {
final Cupboard cupboard = new Cupboard(5);//创建面包柜,容量为5个面包
//创建三个面包师线程和三个伙计线程,并启动。每个面包师烤一百个面包,每个伙计销售一百个面包。
for(int i=1;i<=3;i++) {
//面包师线程
new Thread("面包师"+i) {
public void run() {
for(int i=0;i<100;i++) {
cupboard.add();
}
}
}.start();
//伙计线程
new Thread("伙计"+i) {
public void run() {
for(int i=0;i<100;i++) {
cupboard.remove();
}
}
}.start();
}
}
}
Java高级应用:反射
概述:人想要知道自己的模样,可以通过照镜子看自己的特征。java想要知道本身的特征,通过反射。
反射:
反射机制是在【运行状态】中
对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用他的任意一个方法和属性;
反射提供的功能
a.在运行时判断任意一个对象所属的类
b.在运行时构造任意一个类的对象
c.在运行时判断任意一个类所具有的成员变量和方法
e.在运行时调用任意一个对象的方法
f.生成动态代理
User.java
package demo2;
public class User {
private int id;
private String name;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", address=" + address + "]";
}
public User(int id, String name, String address) {
this.id = id;
this.name = name;
this.address = address;
}
public User() {
}
public static void staticMethod() {
System.out.println("静态方法。。。。");
}
}
- 反射的三种入口方式
ReflectTest.java
package demo2;
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException {
// 反射的入口1
Class<?> userClazz1 = Class.forName("demo2.User");
System.out.println(userClazz1);
// 反射的入口2
User user = new User();
Class<?> userClazz2 = user.getClass();
System.out.println(userClazz2);
// 反射的入口3
Class<?> userClazz3 = User.class;
System.out.println(userClazz3);
}
}
注意:上示的userClazz1,userClazz2,userClazz3之间任意两个的equals()方法都为true,并且三个的hashCode()方法得到的哈希码值都相等
- 反射获取属性和方法
// 获取所有的公共方法
public static void test2() throws ClassNotFoundException {
// 反射的入口1
Class<?> userClazz1 = Class.forName("demo2.User");
// 获得该类的公共(本类,父类,接口中的方法public修饰的)方法
Method[] methods = userClazz1.getMethods();
// 测试方法
for (Method method : methods) {
System.out.println(method);
}
}
// 获取接口名称
public static void test3() throws ClassNotFoundException {
// 反射的入口1
Class<?> userClazz1 = Class.forName("demo2.User");
// 获取接口
Class<?>[] interfaces = userClazz1.getInterfaces();
// 遍历接口
for (Class inter : interfaces) {
System.out.println(inter);
}
}
// 获取父类(Java单继承,只有一个父类)
public static void test4() throws ClassNotFoundException {
// 反射的入口1
Class<?> userClazz1 = Class.forName("demo2.User");
// 获取父类
Class<?> superclass = userClazz1.getSuperclass();
System.out.println(superclass);
}
// 获取该类的所有构造方法
public static void test5() throws ClassNotFoundException {
// 反射的入口1
Class<?> userClazz1 = Class.forName("demo2.User");
// 获取该类构造方法
Constructor<?>[] constructors = userClazz1.getConstructors();
// 获取该类构造方法(不包含父类,忽略修饰符)
Field[] declaredFields = userClazz1.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println();
}
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
// 获取该类的公共属性
public static void test6() throws ClassNotFoundException {
// 反射的入口1
Class<?> userClazz1 = Class.forName("demo2.User");
// 获取该类构造方法
Field[] fields = userClazz1.getFields();
for (Field field : fields) {
System.out.println(field);
}
}
// 获取当前类的所有方法(只能时该类,忽略访问修饰符的限制)
public static void test7() throws ClassNotFoundException {
// 反射的入口1
Class<?> userClazz1 = Class.forName("demo2.User");
// 获取该类的所有方法(只能时该类,忽略访问修饰符的限制)
Method[] declaredMethods = userClazz1.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
}
// 获取当前类所代表的对象(实例)
public static void test8() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
// 反射的入口1
Class<?> userClazz1 = Class.forName("demo2.User");
// 代表的对象
User newInstance1 = (User) userClazz1.newInstance();
newInstance1.show1();
User newInstance2 = (User) userClazz1.newInstance();
newInstance2.show2();
}
- 反射操作属性和方法
// 操作构造方法
private static void test3() throws ClassNotFoundException, NoSuchMethodException, SecurityException {
// TODO Auto-generated method stub
// 反射入口1
Class<?> userClazz = Class.forName("demo2.User");
// 公共构造方法
// Constructor<?>[] constructors = userClazz.getConstructors();
// 获取本类的所有构造(忽略访问权限修舒服)
// Constructor<?>[] declaredConstructors = userClazz.getDeclaredConstructors();
// 获取本类的指定的构造方法(忽略访问权限修舒服)
// 根据基本类型(int char float...)和包装类(Integer Float Char...)
Constructor<?> declaredConstructor = userClazz.getDeclaredConstructor(int.class);
System.out.println(declaredConstructor);
}
private static void test21() throws ClassNotFoundException, InstantiationException, IllegalAccessException,
NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
// TODO Auto-generated method stub
// 反射入口1
Class<?> userClazz = Class.forName("demo2.User");
// 反射获取User类的对象
User user = (User) userClazz.newInstance();
// 获取方法
Method method = userClazz.getDeclaredMethod("print", String.class);
// 私有的,设置方法的可见性
method.setAccessible(true);
// 相当于:对象.set("str");
method.invoke(user, "zhangsan");
}
// 反射操作方法
private static void test2() {
// TODO Auto-generated method stub
}
// 反射操作属性,对象
private static void test1() throws ClassNotFoundException, InstantiationException, IllegalAccessException,
NoSuchFieldException, SecurityException {
// 反射入口1
Class<?> userClazz = Class.forName("demo2.User");
// 反射获取User类的对象
User user = (User) userClazz.newInstance();
// 获取方法
Field declaredField = userClazz.getDeclaredField("id");
// id为私有,该方法解决修饰符带来的问题(Filed有,Method也有)
declaredField.setAccessible(true);
// 赋值,相当于:对象.set(值);
declaredField.set(user, 1);
// 输出
System.out.println(user.getId());
}
- 动态加载类和方法
配置文件:config.properties
classname=demo2.Student
methodname=syaHiv
private static void dynamicLoadClassMethod() throws Exception, Exception {
// 创建配置文件对象
Properties pro = new Properties();
// 加载配置文件
pro.load(new FileReader("config.properties"));
// 动态获取类名
String classname = pro.getProperty("classname");
// 动态获取方法名
String methodname = pro.getProperty("methodname");
// 获取类的class文件对象
Class<?> clazzName = Class.forName(classname);
// 获取方法对象
Method method = clazzName.getDeclaredMethod(methodname);
// 回调方法
method.invoke(clazzName.newInstance());
}
-
反射越过泛型检查
-
虽然反射能越过泛型检查和private修饰符(见上),但不建议这样做。
//反射越过反省检查
private static void dynamicLoadClassMethod1() throws Exception{
//集合对象
ArrayList<Integer> list=new ArrayList<>();
list.add(1);
list.add(2);
//获取集合对象的字节码对象
Class<?> clazzList = list.getClass();
//获取add方法的对象
Method method = clazzList.getMethod("add", Object.class);
//回调方法
method.invoke(list, "hello");
//打印集合
System.out.println(list);
}
- 万能赋值方法
/**
* 万能赋值方法
* @param obj 给那个对象赋值
* @param fildName 对象的哪个属性
* @param value 赋的什么值
* @throws Exception
*/
private static void dynamicLoadClassMethod2(Object obj,String fildName,Object value) throws Exception{
//获取字节码对象
Class<?> clazz = obj.getClass();
//获得属性
Field declaredField = clazz.getDeclaredField(fildName);
//越过private修饰符
declaredField.setAccessible(true);
//赋值:setXxxx("");
declaredField.set(obj, value);
}
加密与解密
- 异或:可逆
public class SecurityUtil {
/**
* 加密与解密
* @param input 对哪个字符串加密
* @param number 对那个数字加密
* @return 加密的结果
*/
public static String xor(String input,int number) {
//将字符串变为字符数组
char[] charArray = input.toCharArray();
//遍历数组
for(int i=0;i<charArray.length;i++) {
//将数组中每个 元素进行加密
charArray[i]=(char)(charArray[i]^number);
}
return new String(charArray);
}
public static void main(String[] args) {
//加密
String xor = SecurityUtil.xor("11",200);
System.out.println(xor);
//解密
xor = SecurityUtil.xor(xor,200);
System.out.println(xor);
}
}
- MD5和sha256加密:不可逆
/**
* 效率高
* 安全性能低
* 需要引入commons-codec的jar包
* MD5加密:不可逆,安全
* @param input 对那个字符串进行加密
* @return 加密的结果
*/
public static String md5Encode(String input) {
byte[] bytes = input.getBytes();
String md5Hex = DigestUtils.md5Hex(bytes);
return md5Hex;
}
/**
* 效率第
* 安全性能高
* 需要引入commons-codec的jar包
* @param input 加密的字符串
* @return 加密后的结果
*/
public static String sha256Encode(String input) {
return DigestUtils.sha256Hex(input.getBytes());
}
- 使用base64加密(jdk提供):可逆
/**
* 加密:jdk自带
* @param input
* @return
* @throws Exception
*/
public static String base64Encode(String input) throws Exception {
//反射入口
Class<?> clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
//获取encode方法对象
Method method = clazz.getMethod("encode", byte[].class);
//加密的结果
String result = (String)method.invoke(null, input.getBytes());
//将结果返回
return result;
}
/**
* 解密:jdk自带
* @param input
* @return
* @throws Exception
*/
public static byte[] base64Decode(String input) throws Exception {
byte[] bt=null;
//反射入口
Class<?> clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
//获取encode方法对象
Method method = clazz.getMethod("decode", String.class);
//加密的结果
bt = (byte[])method.invoke(null, input);
//将结果返回
return bt;
}
二维码生成
-
目录结构
-
QRCodeUtil.java
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import com.swetake.util.Qrcode;
import jp.sourceforge.qrcode.QRCodeDecoder;
import jp.sourceforge.qrcode.data.QRCodeImage;
import jp.sourceforge.qrcode.exception.DecodingFailedException;
public class QRCodeUtil {
//加密: 文字信息 ->二维码.png
/*
* imgPath:src/二维码.png
* content: 文字信息
* imgType:png
*/
public void encoderQRCode(String content,String imgPath,String imgType,int size) throws Exception{
//BufferedImage :内存中的一张图片
BufferedImage bufImg = qRcodeCommon(content,imgType,size);
File file = new File(imgPath);// "src/二维码.png" --> 二维码.png
//生成图片
ImageIO.write(bufImg, imgType, file) ;
}
//产生一个二维码的BufferedImage
/*
*content:二维码中隐藏的信息
*imgType:图片格式
*size :二维码边长
*/
public BufferedImage qRcodeCommon(String content ,String imgType,int size) throws Exception{
BufferedImage bufImg = null ;
//Qrcode对象:字符串->boolean[][]
Qrcode qrCodeHandler = new Qrcode();
//设置二维码的排错率:7% L<M<Q<H30% :排错率越高,可存储的信息越少;但是对二维码清晰对要求越小
qrCodeHandler.setQrcodeErrorCorrect('M');
//可存放的信息类型:N:数字、 A:数字+A-Z B:所有
qrCodeHandler.setQrcodeEncodeMode('B');
//尺寸:取值范围:1-40
qrCodeHandler.setQrcodeVersion(size);
byte[] contentBytes = content.getBytes("UTF-8") ;//"Hello world" -> byte[]"Hello world"
// -->boolean[][]
boolean[][] codeOut = qrCodeHandler.calQrcode(contentBytes) ;
int imgSize = 67 + 12*(size -1) ;
//BufferedImage:内存中的图片
bufImg = new BufferedImage(imgSize,imgSize,BufferedImage.TYPE_INT_RGB );//red green blue
//创建一个画板
Graphics2D gs = bufImg.createGraphics() ;
gs.setBackground(Color.WHITE);//将画板的背景色设置为白色
gs.clearRect( 0,0, imgSize,imgSize); //初始化
gs.setColor(Color.BLACK);//设置 画板上 图像的颜色(二维码的颜色)
int pixoff = 2 ;
for(int j=0;j<codeOut.length;j++) {
for(int i=0;i<codeOut.length;i++) {
if(codeOut[j][i]) {
gs.fillRect(j*3+pixoff , i*3+pixoff, 3, 3);
}
}
}
//增加LOGO
//将硬盘中的src/logo.png 加载为一个Image对象
Image logo = ImageIO.read(new File("src/logo.png") ) ;
int maxHeight = bufImg.getHeight() ;
int maxWdith = bufImg.getWidth() ;
//在已生成的二维码上 画logo
gs.drawImage(logo,imgSize/5*2,imgSize/5*2, maxWdith/5,maxHeight/5 ,null) ;
gs.dispose(); //释放空间
bufImg.flush(); //清理
return bufImg ;
}
//解密: 二维码(图片路径) -> 文字信息
public String decoderQRCode(String imgPath) throws Exception{
//BufferedImage内存中的图片 :硬盘中的imgPath图片 ->内存BufferedImage
BufferedImage bufImg = ImageIO.read( new File(imgPath) ) ;
//解密
QRCodeDecoder decoder = new QRCodeDecoder() ;
TwoDimensionCodeImage tdcImage = new TwoDimensionCodeImage(bufImg);
byte[] bs = decoder.decode(tdcImage) ; //bufImg
//byte[] -->String
String content = new String(bs,"UTF-8");
return content;
}
}
- TwoDimensionCodeImage.java
import java.awt.image.BufferedImage;
import jp.sourceforge.qrcode.data.QRCodeImage;
public class TwoDimensionCodeImage implements QRCodeImage {
BufferedImage bufImg; //将图片加载到内存中
public TwoDimensionCodeImage(BufferedImage bufImg) {
this.bufImg = bufImg;
}
@Override
public int getHeight() {
return bufImg.getHeight();
}
@Override
public int getPixel(int x, int y) {
return bufImg.getRGB(x, y);
}
@Override
public int getWidth() {
return bufImg.getWidth();
}
}
- Test.java
public class Test {
public static void main(String[] args) throws Exception{
//生成二维码
/*
* 生成图片的路径 src/二维码.png
* 文字信息、网址信息 : "helloworld"
*/
String imgPath = "src/mycsdn2.png";
String content = "https://blog.csdn.net/userzhaopan"; //扫描二维码后,网页跳转
//生成二维码
/*
* 加密: 文字信息 ->二维码
* 解密: 二维码 -> 文字信息
*/
QRCodeUtil qrUtil = new QRCodeUtil();
//加密: 文字信息 ->二维码
qrUtil.encoderQRCode(content, imgPath, "png", 17);
// TwoDimensionCode handler = new TwoDimensionCode();
// handler.encoderQRCode(content, imgPath, "png", 7);
// //解密: 二维码 -> 文字信息
String imgContent = qrUtil.decoderQRCode(imgPath) ;
System.out.println(imgContent);
}
}