写点什么

【Java 强化】代码规范,springcloud 视频

用户头像
极客good
关注
发布于: 刚刚

private static Map<String, IUSB> plugins = new HashMap<>();


//-----------------------静态代码快加载资源文件-------------------------


static {


Properties p = new Properties();


// 从 classpath 的根路径去加载 plugins.properties 文件


try (InputStream is = Thread.currentThread()


.getContextClassLoader()


.getResourceAsStream("plugins.properties"))


{


p.load(is);


// 读取 properties 文件, 创建 USB 组件对象


Set<Entry<Object, Object>> entrys = p.entrySet();


for (Entry<Object, Object> entry : entrys) {


// 资源文件中读取到的类名


String className = entry.getValue().toString();


// 通过反射利用类名创建对象


IUSB usbObject = (IUSB)Class.forName(className).newInstance();


plugins.put(entry.getKey().toString(), usbObject);


}


} catch (Exception e) {


e.printStackTrace();


}


}


//-------------------------------------------------------------------


// 将配件插在主板上


public void install(String name, IUSB usb) {


plugins.put(name, usb);


}


// 从主板上卸载指定的配件


public void uninstall(String name) {


plugins.remove(name);


}


// 主板通信, 让每个配件都工作


public void doWork() {


for (IUSB usb : plugins.values()) {


usb.swapData();


}


}


}


此时 APP 中的代码将变得十分简洁,我们无需再手动创建配件对象再调用主板的 install,我们只需要维护好配置文件 plugins.properties 中的内容即可。


比如,我们写一个键盘类 Keyboard


public class Keyboard implements IUSB{


@Override


public void swapData() {


System.out.println("键盘在跳舞");


}


}


我们只需要将它添加到配置文件中即可。

key=value

mouse = com.yusael._01_review.Mouse


keyboard = com.yusael._01_review.Keyboard


APP 中的代码是不需要动的。


public class App {


public static void main(String[] args) {


// 主板对象,


MotherBoard board = new MotherBoard();


// 调用主板的通信


board.doWork();


System.out.println("-----------------------");


}


}


键盘在跳舞


鼠标在移动




[](


)JavaBean 规范


==============================================================================


JavaBean 是一种 JAVA 语言写成的可重用组件(类),必须遵循一定的规范:


  1. 类必须使用 public 修饰

  2. 必须保证有公共无参数构造器

  3. 包含了属性的操作手段(gettersetter


分类:


  • 复杂:UI,比如 ButtonPanelWindow

  • 简单:domaindaoservice组件、封装数据、操作数据库、逻辑运算等


成员:


  • 方法:Method

  • 事件:event

  • 属性:property


属性:


  1. attribute:表示状态,Java 中没有该概念,很多人把 字段(Field) 称之为 属性(attribute)

  2. property:表示状态,但是不是字段,是字段的操作方法(getter/setter)决定的


框架中使用的大多是是属性。


设置字段值:writeMethod: setter 方法:


public void setXxx(数据类型 变量){


赋值操作;


}


若:setName ----> 属性:name


若:setUserName ----> 属性:userName


若:setISBN ----> 属性:ISBN


获取字段值:readMethod: getter方法:


public 数据类型 getXxx(){


return 结果值;


}


若:getName ----> 属性:name


若:getUserName----> 属性:userName


若:getISBN ----> 属性:ISBN


若:数据类型是 boolean,则不叫 get 方法,而是 is 方法,如:isEmpty


标准的属性:一般提供字段,Eclipse 生成 getter/setter字段和属性同名


是否需要同时提供 getter/setter


public class User{


private String firstName; // 名


private String lastName; // 性别


//在数据库只需要存储全名


public void setFullName(String fullName){}


}


面试题:说说 JavaBean 和 EJB 的区别。


[](


)Lombok 工具(减少代码量)


===================================================================================


一、Lombok 是什么


Lombok 是一款小巧的代码生成工具。官方网址:[http://projectlombok.org/](


)


Lombok 主要特性有:自动生成默认的 getter/setter 方法、自动化的资源管理(通过@Cleanup注解)及注解驱动的异常处理等。目前在国外广泛应用。


Lombok 它和 jquery 一样,目标是让程序员写更少的代码,以及改进一些原始语法中不尽人意的地方。Lombok 能做到这一点。既不是用 annotations process,也不是用反射。而是直接黑到了编译过程中。所以对运行效率没有任何影响,我们可以通过反编译 class 文件进行验证。


二、为何项目中要引入 Lombok


  1. 提高开发效率

  2. 使代码直观、简洁、明了、减少了大量冗余代码(一般可以节省 60%-70%以上的代码)

  3. 极大减少了后期维护成本

  4. 修改变量名不需要再手动修改 getter/setter


三、使用 Lombok


  1. 给 Eclipse 安装插件,识别语法

  2. 在项目中引入 lombok 包

  3. 使用其中的注解(标签)


注意:构造器 和 toSring 也可以使用 lombok,但是建议写出来,看的更明显。


import lombok.Getter;


import lombok.Setter;


@Getter@Setter


public class Person {


private Long id;


private String name;


private Integer age;


public Person(Long id, String name, Integer age) {


this.id = id;


this.name = name;


this.age = age;


}


@Override


public String toString() {


return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";


}


}


Ctrl + O 可以看到当前类的字段方法getter/setter 已经存在。



[](


)内省机制(Introspector)(重要)


=========================================================================================


内省机制作用:查看和操作 JavaBean 中的属性


  • 获取 JavaBean 中的每一个属性名/属性类型

  • 通过 getter 方法获取属性值;通过 setter 方法给属性设置值


首先创建一个类 User


public class User {


private String name;


private int age;


private boolean man;


public String getName() {


return name;


}


public void setName(String name) {


this.name = name;


}


public int getAge() {


return age;


}


public void setAge(int age) {


this.age = age;


}


public boolean isMan() {


return man;


}


public void setMan(boolean man) {


this.man = man;


}


}


下面是一个关于内省机制的例子:


import java.beans.BeanInfo;


import java.beans.Introspector;


import java.beans.PropertyDescriptor;


import java.lang.reflect.Method;


// 内省机制: 操作 User 类值的属性


public class IntrospectorDemo {


public static void main(String[] args) throws Exception {


// 1:获取 JavaBean 的描述对象


BeanInfo beanInfo = Introspector.getBeanInfo(User.class, Object.class);


User u = User.class.newInstance();


// 2:获取 JavaBean 中的属性的描述器


PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();


System.out.println(u); // 证明是同一个对象


for (PropertyDescriptor pd : pds) {


// 获取当前属性的名称


System.out.println("属性名 = " + pd.getName());


// 获取当前属性的 getter 方法


System.out.println("getter : " + pd.getReadMethod());


// 获取当前属性的 setter 方法


System.out.println("setter : " + pd.getWriteMethod());


System.out.println("--------------------------------");


if ("name".equals(pd.getName())) {


Method setter = pd.getWriteMethod(); // 获取方法


setter.invoke(u, "Jack"); // 调用方法


}


}


System.out.println(u);


}


}


[](


)apache 的 commons 项目(了解)


=========================================================================================


这部分内容了解一下就可以,知道 apache 有很多强大的项目,commons 是其中之一。



[](


)JavaBean 和 Map 相互转换(自行实现)




  • JavaBean 拥有多组属性名和属性值,每一个属性名称对应一个属性值,属性名称不同。

  • Map 拥有多组 key-value,每一个 key 对应一个 value,key 不同。


如果把 JavaBean 中的属性名称看做是 Map 中的 key,二者就是等价的。



把 JavaBean 转换为 Map 对象:


  • public static Map<String,Object> bean2map(Object bean){}


把 Map 对象转换为 JavaBean:


  • public static Object map2bean(Map<String,Object> beanMap,Class beanType){}


import java.beans.BeanInfo;


import java.beans.Introspector;


import java.beans.PropertyDescriptor;


import java.util.HashMap;


import java.util.Map;


import com.yusael._02_javabean.Person;


// JavaBean 的工具类


public class BeanUtil {


public static void main(String[] args) throws Exception {


Person p = new Person();


p.setId(123L);


p.setName("Jack");


p.setAge(18);


// JavaBean -> Map


Map<String, Object> map = bean2map(p);


System.out.println(map);


// Map -> JavaBean


Person obj = map2bean(map, Person.class);


System.out.println(obj);


}


// 把 JavaBean 对象转换为 Map


public static Map<String, Object> bean2map(Object bean) throws Exception {


Map<String, Object> map = new HashMap<>();


BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass(), Object.class);


PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();


for (PropertyDescriptor pd : pds) {


String name = pd.getName(); // 属性名称


Object value = pd.getReadMethod().invoke(bean); // 调用 getter 方法, 获取属性值


map.put(name, value);


}


return map;


}


// 把 Map 转换为 JavaBean


public static <T> T map2bean(Map<String, Object> map, Class<T> beanType) throws Exception {


// 创建 JavaBean 对象


Object obj = beanType.newInstance();


BeanInfo beanInfo = Introspector.getBeanInfo(beanType, Object.class);


PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();


for (PropertyDescriptor pd : pds) {


// 从 Map 中获取和属性同名的 key 的值


Object value = map.get(pd.getName());


// 调用 setter 方法, 设置属性值


pd.getWriteMethod().invoke(obj, value);


}


return (T)obj;


}


}


[](


)commons-beanutils(了解、体验一下使用即可)




这部分了解一下即可,大概体验一下这些工具类的作用。。。


需要 jar 包:commons-beanutils-1.9.4.jarcommons-logging-1.2.jar



import java.util.HashMap;


import java.util.Map;


import org.apache.commons.beanutils.BeanUtils;


import com.yusael._02_javabean.Person;


public class BeanUtilsDemo {


public static void main(String[] args) throws Exception {


Person p = new Person();


Map<String, Object> map = new HashMap<>();


map.put("id", "17210224");


map.put("name", "Jack");


map.put("age", "20");


System.out.println(p);


BeanUtils.copyProperties(p, map);


System.out.println(p);


}


}


转换时的一些细节:直接转换 long 类型的缺省值为 0,需注册为 Long,缺省值才为 null;




日期类转换的细节:beanutils 不支持 String --> Date 转换,需要手动设置转换模式。



[](


)注解(Annotation)


=================================================================================


[](


)初始注解




Java5 开始,java 开始对元数据的支持,也就是 Annotation注解 / 标签


  • 元数据(metadata):描述数据的数据

  • 注解被用来为程序元素(类,方法,成员变量等)设置元数据。


所有的 Annotation 都是 java.lang.annotation.Annotation 接口的子接口


  • Annotation 是一种特殊的接口(好比枚举是特殊的类);


@interface Override {} ---> interface Override extends java.lang.annotation.Annotation{}


所有的枚举类,都是 java.lang.Enum 类的子类


enum Gender{} ---- > class Gender extends java.lang.Enum{}


使用注解需要注意,必须有三方参与才有意义:


  1. 得有注解标签;

  2. 被贴的程序元素(类、字段、构造器、方法等);

  3. 第三方的程序来赋予注解特殊的功能(也是 Java 代码);



[](


)JDK 自带的注解




  • @Override:限定覆写父类方法

  • @Deprecated:标记已过时不推荐使用


在 JDK1.5 之前,使用文档注释来标记过时



  • @SuppressWarings:抑制编译器发出的警告


@SuppressWarings(value="all")


  • @SafeVarargs:抑制堆污染警告(Java7 开始出现的)


该注解仅仅是抑制住编译器不要报警告,但是存在的风险依然存在。


使用注解存在的疑惑:


  1. 为什么有的注解可以贴在类上/方法上/变量上,而有些却不行?


肯定有东西来约束注解贴的位置。


  1. 为什么有的注解可以接受参数,比如@SuppressWarings(value="all"),而有的注解却不行。


通过查看注解的源代码,发现注解中存在抽象方法才可以使用参数



[](


)元注解(@Retention、@Target、@Documented、@Inherited)




元注解:注解的元数据 —> 定义注解时,注解上的注解。



@Retention: 表示注解可以保存在哪一个时期;保存的时期的值,封装在 RetentionPolicy 枚举类中;一般自定义的注解,使用RUNTIME(使用反射赋予注解功能)


  • SOURCE:注解只能存在于源文件中,编译之后,字节码文件中没有。

  • CLASS: 注解可以存在于源文件和字节码文件中,无法加载进 JVM。

  • RUNTIME:注解可以存在于源文件,字节码文件,JVM 中。



@Target表示注解可以贴在哪些位置(类、方法、构造器上等等)


位置的常量封装在 ElementType 枚举类中:


* ElementType.ANNOTATION_TYPE:只能修饰 Annotation


* ElementType.CONSTRUCTOR:只能修饰构造方法


* ElementType.FIELD:只能修饰字段,包括枚举常量


* ElementType.LOCAL_VARIABLE:只能修饰局部变量


* ElementType.METHOD:只能修饰方法


* ElementType.PACKAGE:只能修饰(极少使用)


* ElementType.PARAMETER:只能修饰参数


* ElementType.TYPE:只能修饰类,接口,枚举


@Documented: 使用 @Documented 标注的标签会保存到 API 文档中


@Inherited: @Inherited 标注的标签可以被子类所继承


@Target(RetentionPolicy=RUNTIME)


@Target(ElementType.TYPE)


@Inherited


@interface A{} // 定义一个 A 标签




@A


class SuperClass{} // 使用 A 标签




// SubClass 是 SuperClass 的子类


// 使用反射来检测 SubClass, 发现 SubClass 类上也有 A 标签


// 说明 A 标签 被继承了


class SubClass{}


[](


)注解的定义和使用




注解的定义语法:


@Target(ElementType.TYPE) // 标识该注解可以贴在类上/接口上


@Retention(RetentionPolicy.RUNTIME) // 标识该注解可以存在于 JVM 中(通过反射赋予功能)


public @interface 注解名称 {


// 抽象方法-->属性


返回类型 方法名称() default 值;


...


}


注意:注解中 抽象方法(属性) 类型


  • 只能是 基本类型、StringClassannotation、枚举 、数组

  • 当只有一个属性并且名称为 value,此时可以省略 value


// @VIP(value="xx")

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
【Java 强化】代码规范,springcloud视频