欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Base64j加密解密、动态代理、正则表达式、单例多例设计模式、枚举、工厂设计模式

时间:2023-06-08
base64的加密和解密(jdk8新特性)(重点)

public class Demo01base64 { public static void main(String[] args) { String s1 = "国家的绝密文件!"; System.out.println("原字符串:"+s1);//原字符串:国家的绝密文件! //使用加密器Encoder中的方法encodeToString​把字符串进行加密 String s2 = base64.getEncoder().encodeToString(s1.getBytes()); System.out.println("加密后的字符串:"+s2);//加密后的字符串:5Zu95a6255qE57ud5a+G5paH5Lu2IQ== //使用解密器Decoder中的方法decode把加密后的字符串进行解密 byte[] bytes = base64.getDecoder().decode(s2); String s3 = new String(bytes); System.out.println("解密后的字符串:"+s3); }}

动态代理(原理) 动态代理概述 动态代理代码实现

Star接口

//培养明星的接口public interface Star { //培养唱歌的方法 public abstract void changge(); //培养跳舞的方法 public abstract void tiaowu(); //培养演电影的方法 public abstract String yandianying(int money); //培养吃饭的方法 public abstract void chifan(); //培养玩游戏的方法 public abstract void wanyouxi();}

Caixukun类

public class CaiXuKun implements Star { @Override public void changge() { System.out.println("蔡徐坤在唱歌"); } @Override public void tiaowu() { System.out.println("蔡徐坤在跳舞+打篮球"); } @Override public String yandianying(int money) { System.out.println("蔡徐坤在演电影"+money); return "电影演完了"; } @Override public void chifan() { System.out.println("和蔡徐坤一起吃饭"); } @Override public void wanyouxi() { System.out.println("和蔡徐坤一起玩游戏"); }}

WuQian类

public class WuQian implements Star { @Override public void changge() { System.out.println("吴Q在唱歌"); } @Override public void tiaowu() { System.out.println("吴Q在跳舞"); } @Override public String yandianying(int money) { System.out.println("吴Q在演电影"+money); return "电影演完了"; } @Override public void chifan() { System.out.println("吴Q吃大锅饭"); } @Override public void wanyouxi() { System.out.println("吴Q踩缝纫机"); }}

InvocationHandler接口的实现类

public class InvocationHandlerImpl implements InvocationHandler { //在实现类中定义一个变量为Star类型 private Star star; public InvocationHandlerImpl(Star star) { this.star = star; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //获取到方法名称 String methodName = method.getName(); //对方法名称进行判断 if("chifan".equals(methodName)){ throw new RuntimeException("不和你吃饭!"); } if("wanyouxi".equals(methodName)){ throw new RuntimeException("不和玩游戏!"); } //其他的方法,使用Method类的方法invoke让方法运行 Object v = method.invoke(star, args); return v; }}

测试类:

public class Demo01Proxy { public static void main(String[] args) { //没有使用动态代理 CaiXuKun cxk = new CaiXuKun(); //cxk.changge(); //cxk.tiaowu(); //获取蔡徐坤的代理人对象 Star cxkProxy = (Star) Proxy.newProxyInstance(CaiXuKun.class.getClassLoader(), CaiXuKun.class.getInterfaces(),new InvocationHandlerImpl(cxk)); cxkProxy.changge(); cxkProxy.tiaowu(); String s = cxkProxy.yandianying(100); System.out.println(s); //cxkProxy.chifan(); //cxkProxy.wanyouxi(); //获取吴Q的代理人对象 Star wqProxy = (Star)Proxy.newProxyInstance(WuQian.class.getClassLoader(), WuQian.class.getInterfaces(),new InvocationHandlerImpl(new WuQian())); wqProxy.changge(); wqProxy.tiaowu(); wqProxy.chifan(); }}

动态代理综合案例

需求:
模拟Collections的unmodifiableList方法,对List接口进行代理
调用List接口的方法会被拦截
如果使用的size,get方法,没有对集合进行修改,则允许执行
如果使用的add,remove,set方法,对集合进行了修改,则抛出运行时异常

分析:
1.定义一个代理方法proxyList
参数:传递List集合
返回值:被代理之后的List集合
2.方法内部可以使用Proxy类中的方法实现动态代理

代码实现:

public class Demo02Proxy { public static void main(String[] args) { //创建List对象 List list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); //调用proxyList方法,获取List接口的代理人对象 List listProxy = proxyList(list); System.out.println(listProxy.size());//3 System.out.println(listProxy.get(1));//b listProxy.remove(0);//UnsupportedOperationException: remove no run } //1.定义一个代理方法proxyList public static List proxyList(List list){ //2.方法内部可以使用Proxy类中的方法实现动态代理 List listProxy = (List)Proxy.newProxyInstance(Demo02Proxy.class.getClassLoader(), list.getClass().getInterfaces(),new InvocationHandlerImpl(list)); return listProxy; }}

public class InvocationHandlerImpl implements InvocationHandler { //定义一个List集合的变量 private List list; public InvocationHandlerImpl(List list) { this.list = list; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //invoke方法会获取list集合中的方法,在invoke方法内部对list集合的方法进行拦截 //获取方法的名称 String methodName = method.getName(); //如果使用的add,remove,set方法,对集合进行了修改,则抛出运行时异常 if("add".equals(methodName)){ throw new UnsupportedOperationException("add no run"); } if("remove".equals(methodName)){ throw new UnsupportedOperationException("remove no run"); } if("set".equals(methodName)){ throw new UnsupportedOperationException("set no run"); } //如果使用的size,get方法,没有对集合进行修改,则允许执行 Object v = method.invoke(list, args); return v; }}

动态代理案例流程图

总结

动态代理非常的灵活,可以为任意的接口实现类对象做代理

动态代理可以为被代理对象的所有接口的所有方法做代理,动态代理可以在不改变方法源码的情况下,实现对方法功能的增强,

动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。
动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。

动态代理同时也提高了开发效率。

缺点:只能针对接口的实现类做代理对象,普通类是不能做代理对象的。

正则表达式(重点) 正则表达式的概念及演示

public class Demo01Regex { public static void main(String[] args) { //获取一个用户输入的QQ号 System.out.println("请输入一个QQ号:"); String qq = new Scanner(System.in).nextLine(); boolean b1 = checkQQ(qq); System.out.println("b1:"+b1); boolean b2 = checkQQRegex(qq); System.out.println("b2:"+b2); } //定义校验QQ号的方法,不使用正则表达式 public static boolean checkQQ(String qq){ //1.长度5-15位 if(qq.length()<5 || qq.length()>15){ return false; } //2.全是数字 char[] chars = qq.toCharArray(); for (char c : chars) { //判断字符是否在'0'到'9'之间 if(c<'0' || c>'9'){ return false; } } //3.第一位不是是0 if("0".equals(qq.charAt(0)+"")){ return false; } //满足所有的规则 return true; } public static boolean checkQQRegex(String qq){ return qq.matches("[1-9][0-9]{4,14}"); }}

正则表达式-字符类

public class Demo02Regex { public static void main(String[] args) { String str = "ead";//false //1.验证str是否以h开头,以d结尾,中间是a,e,i,o,u中某个字符 String regex = "h[aeiou]d"; str = "hid";//true str = "Hud";//false boolean b1 = str.matches(regex); System.out.println("b1:"+b1); //2.验证str是否以h开头,以d结尾,中间不是a,e,i,o,u中的某个字符 regex = "h[^aeiou]d"; str = "h1d";//true str = "had";//false boolean b2 = str.matches(regex); System.out.println("b2:"+b2); //3.验证str是否a-z的任何一个小写字符开头,后跟ad regex = "[a-z]ad"; str = "wad";//true str = "1ad";//false boolean b3 = str.matches(regex); System.out.println("b3:"+b3); //4.验证str是否以a-d或者m-p之间某个字符开头,后跟ad regex = "[a-dm-p]ad"; str = "cad";//true str = "ead";//false boolean b4 = str.matches(regex); System.out.println("b4:"+b4); }}

正则表达式-逻辑运算符

public class Demo03Regex { public static void main(String[] args) { String str = "had";//true str = "ead";//false str = "Had";//false //1.要求字符串是小写[a-z]和福音字符[^aeiou]开头,后跟ad String regex = "[[a-z]&&[^aeiou]]ad"; boolean b1 = str.matches(regex); System.out.println("b1:"+b1); //2.要求字符串是aeiou中的某个字符开头,后跟ad regex = "[a||e||i||o||u]ad";//"[a|e|i|o|u]ad"就相当于"[aeiou]" 或运算符是可以省略不写的 str = "aad";//true str = "1ad";//false boolean b2 = str.matches(regex); System.out.println("b2:"+ b2); }}

正则表达式-预定义字符

public class Demo04Regex { public static void main(String[] args) { //1.验证str是否3位数字 String str = "250";//true str = "25a";//false String regex = "[0-9][0-9][0-9]"; regex = "\d\d\d"; boolean b1 = str.matches(regex); System.out.println("b1:"+b1); //2.验证手机号:1开头,第二位:3/5/8,剩下9位都是0-9的数字 regex = "1[358]\d\d\d\d\d\d\d\d\d"; str = "13800138000";//true str = "23800138000";//false str = "138001380001";//false str = "13800138a00";//false boolean b2 = str.matches(regex); System.out.println("b2:"+b2); //3.验证字符串是否以h开头,以d结尾,中间是任何字符 regex = "h.d"; str = "h&d";//true str = "h中d";//true str = "1Ad";//false boolean b3 = str.matches(regex); System.out.println("b3:"+b3); //4.验证str是否是:had. //注意: .不是任意字符,就是一个普通的.需要使用转义字符把有特殊含义的.转换为普通的. regex = "had\."; str = "hadA";//false str = "had.";//true boolean b4 = str.matches(regex); System.out.println("b4:"+b4); }}

正则表达式-数量词

public class Demo05Regex { public static void main(String[] args) { String str = "";//false str = "123";//true str = "1234";//false //1.验证str是否是三位数字 String regex = "\d{3}"; boolean b1 = str.matches(regex); System.out.println("b1:"+b1); //2.验证str是否是多位数字:1次以上的数字 regex = "\d+"; str = "12312413221312";//true str = "1";//true str = "";//false str = "111a";//false boolean b2 = str.matches(regex); System.out.println("b2:"+b2); //3.验证str是否是手机号:1开头,第二位:3/5/8,剩下9位都是0-9的数字 regex = "1[358]\d{9}"; str = "13800138000";//true str = "1380013800a0";//false boolean b3 = str.matches(regex); System.out.println("b3:"+b3); //4.验证小数:必须出现小数点,但是只能出现1次 double d =1.1; d = 0.1; d = .1; d = 1.; //d = .; System.out.println(d); regex = "\d*\.\d+"; str = "1.1";//true str = ".1";//true str = "1.";//true str = "aa.1"; str = "1.1.1"; boolean b4 = str.matches(regex); System.out.println("b4:"+b4); //5.验证小数:小数点可以不出现,也可以出现1次 regex = "\d*\.?\d*"; str = "10000";//true str = "10000.13213123";//true str = ".1212312";//true str = "";//true str = "a";//false str = "a";//false str = "11..11";//false boolean b5 = str.matches(regex); System.out.println("b5:"+b5); //6.验证小数:要求匹配:3、3.、3.14、+3.14、-3. regex = "[+-]?\d+\.?\d*"; str = "3";//true str = "3.";//true str = "3.14";//true str = "+3.14";//true str = "-3.";//true boolean b6 = str.matches(regex); System.out.println("b6:"+b6); //7.验证qq号码:1).5--15位;2).全部是数字;3).第一位不是0 regex = "[1-9]\d{4,14}"; str = "11111";//true str = "111";//false str = "111111a";//false boolean b7 = str.matches(regex); System.out.println("b7:"+b7); }}

正则表达式-分组括号()

public class Demo06Regex { public static void main(String[] args) { String str = "abc";//true str = "";//true str = "abcabc";//true str = "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc";//true str = "abcaaabbbccc";//false //校验字符串"abc"可以出现任意次 String regex = "(abc)*"; boolean b1 = str.matches(regex); System.out.println("b1:"+b1); str = "DG8FV-B9TKY-FRT9J-99899-XPQ4G";//b2:true str = "DG8FV-B9TKY-FRT9J-99899-XPQ4G-";//b2:false //验证这个序列号:分为5组,每组之间使用-隔开,每组由5位A-Z或者0-9的字符组成 regex = "([A-Z0-9]{5}-){4}[A-Z0-9]{5}"; boolean b2 = str.matches(regex); System.out.println("b2:"+b2); }}

String类中和正则表达式相关的方法

public class Demo07Regex { public static void main(String[] args) { show04(); } private static void show01() { String s = "11-22-33-44-55"; String[] arr = s.split("-"); for (String str : arr) { System.out.println(str); } } //正则表达式中.代表任意字符串 private static void show02() { String s = "192.168.1.100"; String[] arr = s.split("\."); System.out.println(arr.length); for (String str : arr) { System.out.println(str); } } private static void show03() { String s = "192 168 1 100"; s = "192 168 1 100"; String[] arr = s.split(" +");//根据一个空格或者多个连续的空格切割字符串 System.out.println(arr.length); for (String str : arr) { System.out.println(str); } } public static void show04(){ String s = "12312asfdsa12123asa11c1fzvs1v*&&3242fsfa11"; System.out.println("原字符串:"+s); //需求:使用replaceAll方法把字符串中每一个数字替换为@_@ String reg = "\d"; String s1 = s.replaceAll(reg, "@_@"); System.out.println("替换后的字符串:"+s1); //需求:使用replaceAll方法把字符串中的连续的数字替换为@_@ reg = "\d+"; String s2 = s.replaceAll(reg,"@_@"); System.out.println("替换后的字符串:"+s2); }}

单例设计模式(重点)

饿汉式

public class Person { //1.私有空参数构造方法,不让用户直接创建对象 private Person(){} //2.定义一个私有的静态的Person变量,并进行初始化赋值 private static Person p = new Person(); //3.定义一个公共的静态方法,返回Person对象 public static Person getInstance(){ return p; }}public class Demo01Singleton { public static void main(String[] args) { //正常情况下,可以根据类创建多个对象 //Person p1 = new Person(); //System.out.println(p1); //Person p2 = new Person(); //System.out.println(p2); //Person p3 = new Person(); //Person p4 = new Person(); //Person p5 = new Person(); //测试单例设计模式,无论调用多少次静态的方法,获取的对象都是同一个 for (int i = 0; i < 20; i++) { Person p = Person.getInstance(); System.out.println(p); } }}

懒汉式

public class Person { //1.私有空参数构造方法,不让用户直接创建对象 private Person(){} //2.在类中定义一个私有的静态的Person变量,不进行初始化赋值 private static Person p; //3.定义一个公共的静态的成员方法,返回Person对象,保证无论调用多少次方法,只返回一个对象 public static Person getInstance(){ //增加一个判断,判断变量p的值是否为null(第一次调用方法),创建对象 if(p == null){ p = new Person(); } //变量p不是null直接返回 return p; }}

解决懒汉式多线程问题

public class Demo01Sigleton { public static void main(String[] args) { //创建两个线程,每个线程获取20次对象 new Thread(()->{ for (int i = 0; i < 20; i++) { Person p = Person.getInstance(); System.out.println(p); } }).start(); new Thread(()->{ for (int i = 0; i < 20; i++) { Person p = Person.getInstance(); System.out.println(p); } }).start(); }}

执行结果

com.llz.demo07Sigleton.Person@2f404fd1
com.llz.demo07Sigleton.Person@67c084e1
com.llz.demo07Sigleton.Person@67c084e1
com.llz.demo07Sigleton.Person@67c084e1


解决方法如下

public class Person { //1.私有空参数构造方法,不让用户直接创建对象 private Person(){} //2.在类中定义一个私有的静态的Person变量,不进行初始化赋值 private static Person p; //3.定义一个公共的静态的成员方法,返回Person对象,保证无论调用多少次方法,只返回一个对象 public static Person getInstance(){ //在外层在增加一个判断,可以提高程序的效率 if(p==null){ synchronized (Person.class){ //增加一个判断,判断变量p的值是否为null(第一次调用方法),创建对象 if(p == null){ p = new Person(); } } } //变量p不是null直接返回 return p; }}

小结
单例模式可以保证系统中一个类只有一个对象实例。

实现单例模式的步骤:

将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。定义一个静态方法返回这个唯一对象。 多例设计模式(重点)

多例模式,是一种常用的软件设计模式。通过多例模式可以保证系统中,应用该模式的类有固定数量的实例。多例类要自我创建并管理自己的实例,还要向外界提供获取本类实例的方法。

例如:

​ 扑克牌程序,一个“扑克类”会创建固定的54个对象,不能多、也不能少。

​ 麻将程序,一个“骰子类”会创建固定的2个对象,不能多、也不能少。

​ 程序中需要用到“颜色的表示”,只能有三种颜色“红、绿、蓝”,一个“颜色类(Color)”应该只创建三个对象,来代 表这三个颜色。

多例模式的作用:使某个类,在程序运行期间,只能产生固定的几个对象,不能多、也不能少。
获取多个通用的对象

public class Student { //1.私有空参数构造方法,不让用户直接创建对象 private Student(){} //2.定义一个私有的,静态的,最终的变量,值定义对象的总个数 private static final int MAX = 3; //3.定义一个自由的,静态的集合,存储多个对象 private static ArrayList list = new ArrayList<>(); //4.定义一个静态代码块,产生3个对象,存储到集合中 static { for (int i = 0; i < MAX; i++) { list.add(new Student()); } } //5.定义一个公共的静态的方法,给用户随机在集合中取出一个对象返回 public static Student getInstance(){ //定义一个Random对象 Random r = new Random(); //在集合索引的范围内,随机产生一个随机数 int index = r.nextInt(list.size());//[0,1,2] //通过产生的随机索引,在集合中获取Student对象返回 return list.get(index); }}

小结
多例模式可以保证系统中一个类有固定个数的实例, 在实现需求的基础上, 能够提高实例的复用性.

实现多例模式的步骤:

创建一个类, 将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。在类中定义该类被创建的总数量在类中定义存放类实例的list集合在类中提供静态代码块,在静态代码块中创建类的实例提供获取类实例的静态方法 枚举(重点)

public enum Sex { MAN("男"),WOMAN("女"); private String s; private Sex(String s) { this.s = s; } //重写toString方法,返回对象中的字符串 @Override public String toString() { return s; }}

public class Demo01Enum { public static void main(String[] args) { //创建Student对象 Student s = new Student(); s.setName("柳岩"); s.setAge(18); s.setSex(Sex.WOMAN); System.out.println(s); }}

枚举的应用

枚举的作用:枚举通常可以用于做信息的分类,如性别,方向,季度等。

枚举表示性别:

public enum Sex { MAIL, FEMAIL;}

枚举表示方向:

public enum Orientation { UP, RIGHT, DOWN, LEFT;}

枚举表示季度

public enum Season { SPRING, SUMMER, AUTUMN, WINTER;}

小结*

枚举类在第一行罗列若干个枚举对象。(多例)第一行都是常量,存储的是枚举类的对象。枚举是不能在外部创建对象的,枚举的构造器默认是私有的。枚举通常用于做信息的标志和分类。 工厂设计模式(重点) 简单工厂设计模式

public class Dog extends Animal { @Override public void eat() { System.out.println("狗吃肉!"); }}public class AnimalFactory { //定义一个静态方法,参数传递动物的名称,根据名称创建指定的动物返回 public static Animal getInstance(String name){ if("cat".equals(name)){ return new Cat(); }else if("dog".equals(name)){ return new Dog(); }else{ //不是动物 return null; } }}public class Demo01SimpleFactory { public static void main(String[] args) { //使用工厂类的方法,获取指定的动物对象 //获取一个Cat对象 Animal cat = AnimalFactory.getInstance("cat"); cat.eat(); //获取一个Dog对象 Animal dog = AnimalFactory.getInstance("dog"); dog.eat(); //胡乱指示一个动物的名称 Animal car = AnimalFactory.getInstance("car"); car.eat();// null.eat(); NullPointerException:抛出了空指针异常 }}

工厂方法设计模式

public class Demo01FactoryMethod { public static void main(String[] args) { //创建生产猫的工厂==>生产猫 CatFactory catFactory = new CatFactory(); Animal cat = catFactory.getInstance(); cat.eat(); //创建生产狗的工厂 ==>生产狗 DogFactory dogFactory = new DogFactory(); Animal dog = dogFactory.getInstance(); dog.eat(); }}public interface Factory { //定义一个抽象的生产动物的方法 public abstract Animal getInstance();}public class CatFactory implements Factory{ @Override public Animal getInstance() { return new Cat(); }}public class DogFactory implements Factory{ @Override public Animal getInstance() { return new Dog(); }}

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。