从零开始学Java-Day18
设计模式
设计模式是Java发展过程中总结出来的一些值得借鉴的优秀编程经验
设计模式一共有23种,主要分为三大类
单例设计模式
核心思想:确保实例只有一个
好处:可以节省内存空间,方便控制资源
实现思路:
- 构造方法私有化--阻止外部直接调用本类的构造方法创建对象
- 创建本类对象且私有化--为了防止外部多次获取本类对象
- 对外提供一个公共全局访问点--按照预先设置的方式来获取对象
饿汉式:加载时事先创建好类的对象
懒汉式:不会再初始化就加载所有资源,在用的时候才加载
单例设计模式方案二:懒汉式
不会再初始化类的时候就创建本类对象,而是用的时候(调用get())才创建
代码实现思路:
- 将创建对象拆分成两步:
- 先定义引用类型变量,默认值null
- 在get()里判断(之前是否创建过),如果没创建过,创建,创建过返回创建的对象.
package cn.tedu.design;
//本类用于测试单例模式实现方式一:饿汉式
public class Singleton1 {
public static void main(String[] args) {
MySingle single = MySingle.getSingle();
MySingle single2 = MySingle.getSingle();
System.out.println(single);
System.out.println(single2);
System.out.println(single == single2);
}
}
/*
*思考:在构造方法与对象被私有化后,需要调用公共的全局访问点来获取本类对象,但是,
* 我们如何调用这个公共方法
* 之前调用方法都是通过类对象进行调用,但单例因为构造方法私有化无法创建对象。
* 解决方案:可以将公共方法设置为静态方法,因此可以直接通过类来调用。
* 因为公共方法是静态的所以类里创建的对象也要静态修饰
*/
class MySingle{
//构造方法私有化:防止外界随意实例化本类对象
private MySingle() {}
private static MySingle single = new MySingle();
public static MySingle getSingle(){
return single;
}
}
package cn.tedu.design;
//单例测试模式方案二:懒汉式--面试重点
public class Singleton2 {
public static void main(String[] args) {
MySingle2 single1 = MySingle2.getMySingle2();
MySingle2 single2 = MySingle2.getMySingle2();
System.out.println(single2);
System.out.println(single1);
System.out.println(single1 == single2);//true
}
}
class MySingle2{
private MySingle2(){}
static private MySingle2 mySingle2;
/*
*在多线程下会有数据隐患
* 解决方案一:同步代码块锁
* 解决方案二:把该方法用 synchronized 修饰
*/
public synchronized static MySingle2 getMySingle2() {
if (mySingle2 == null) {
mySingle2 = new MySingle2();
}
return mySingle2;
}
}
注解与自定义注解
注解很厉害,它可以增强我们的Java代码,同时利用反射技术可以扩充实现很多功能。它们被广泛应用于三大框架底层。
传统我们通过xml文本文件声明方式(如下图,但是XML比较繁琐且不易检查),而现在最主流的开发都是基于注解方式,代码量少,框架可以根据注解去自动生成很多代码,从而减少代码量,程序更易读。例如最火爆的SpringBoot就完全基于注解技术实现。
分三类
-
JDK注解
- @override
-
元注解:用来定义其他注解的注解
- @Target注解用的范围:类上、方法上、属性上等
- @Retention注解的生命周期:源文件中、字节码文件中、运行中
- SOURCE:在源文件中有效(即源文件保留)
- CLASS:在class文件中有效(即class保留)
- RUNTIME:在运行时有效(即运行时保留)
- @Inherited 允许子注解继承
- @Documented 生成javadoc时会包含注解,不常用
- @Repeatable 注解为可重复类型注解,可以在同一个地方多次使用,不常用
-
自定义注解
- 自定义注解需要元注解来指定,语法:@interface 注解名{}
- 使用@Target注解定义自定义注解的作用位置,可以指定多个,格式:
- 使用@Retention注解定义自定义注解的生命周期,只能指定一个
- 使用注解时,@符号 + 注解名直接使用
- 自定义注解可以添加属性
- 普通属性int age(); 赋值格式: @Test(age = 18)
- 特殊属性int value(); 赋值格式:@Test(18)
- 一旦添加了属性必须赋值
- 特殊属性不限制类型,限制的是属性的名字
- 特殊属性和普通属性赋予默认的格式一样 int age() default 15;
package cn.tedu.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//本类用于测试自定义注解,熟悉注解的相关规则
public class TestAnnotation {
public static void main(String[] args) {
new MeiGeMi().skill();
}
}
/*
*0.首先注意:自定义注解的语法和Java不同,不要套用Java格式
*1.注解定义要使用@interface 注解名的方式来定义
* 1.1通过@Target注解来定义当前自定义注解使用的位置| 注意导包 | ElementType.静态常量 | 输入的是一个数组,可以用 , 隔开元素
* 1.2通过使用@Retention注解来定义当前自定义注解使用的生命周期| 注意导包 |RetentionPolicy.静态常量
* 决定注解的存活时间,只能存在一个
*
*/
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
@interface Test{
/*自定义注解可以添加功能--给自定义注解添加属性
* 注意:int age();不是方法的定义,而是自定义注解中定义age属性的语法
* 定义属性后,才使用自定义注解时要在注解后的括号里定义同类型的值,如果在定义属性时
* 赋予默认值了可以直接使用
* 注解中的新功能:定义特殊属性value*/
int height() default 0;
String value() default "一马当先,万马无光";
}
class MeiGeMi{
@Test
String name;
public void skill(){
System.out.println("Explosion!!!!!!!!!!!!!!");
}
}
反射
获取字节码对象
- Class.forName("类的全路径")
- 类名.class
- 对象.getClass();
反射是一种经典常用的技术,通常用来获取或才做其他人的资源
反射的前提是获取字节码对象 + 反射技术获取目标类的所有构造方法
具体方法详见API手册
单元测试方法
package cn.tedu.reflection;
//本类用于测试反射而准备的物料类
public class Student {
String name;
private int age;
private static String skill;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void learn(){
System.out.println("学习!");
}
private void play(String gameName){
System.out.println("冲冲冲!!!" + gameName);
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package cn.tedu.reflection;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
//本类用来测试反射
public class TestReflect1 {
/*单元测试方法:是Java测试的最小单位,使用灵活
* 语法要求:@Test
* void + 没有参数 + public
* 使用时需要导包*/
@Test
public void getClazz() throws ClassNotFoundException {
Class<?> stu1 = Class.forName("cn.tedu.reflection.Student");
Class<Student> stu2 = Student.class;
Class<? extends Student> stu3 = new Student().getClass();
System.out.println(stu1);//class cn.tedu.reflection.Student
System.out.println(stu1.getName());//cn.tedu.reflection.Student
System.out.println(stu2.getPackage().getName());//cn.tedu.reflection
System.out.println(stu3.getSimpleName());//Student
}
@Test
public void getConstruct() throws NoSuchMethodException {
Class<Student> stu = Student.class;
Constructor<?>[] cs = stu.getConstructors();
Method[] method = stu.getMethods();
for (Method method1 : method) {
Class[] cp = method1.getParameterTypes();
System.out.println(Arrays.toString(cp));
}
for (Constructor<?> c : cs) {
//System.out.println(c.getName());
Class[] cp = c.getParameterTypes();
System.out.println(Arrays.toString(cp));
}
}
}
posted on 2021-06-24 19:08 无声specialweek 阅读(40) 评论(0) 编辑 收藏 举报