// 调用主板的通信 board.doWork(); System.out.println("-----------------------"); }
}
键盘在跳舞 鼠标在移动 ----------------------- ``` [](https://gitee.com/vip204888/java-p7)JavaBean 规范 ============================================================================== **JavaBean** 是一种JAVA语言写成的**可重用组件**(类),必须遵循一定的规范: 1. 类必须使用 `public` 修饰 2. 必须保证有公共无参数构造器 3. 包含了属性的操作手段(`getter`,`setter`) 分类: * 复杂:UI,比如 `Button`、`Panel`、`Window` 类 * 简单:`domain`、`dao`、`service`组件、封装数据、操作数据库、逻辑运算等 成员: * 方法:`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 的区别。 [](https://gitee.com/vip204888/java-p7)Lombok 工具(减少代码量) =================================================================================== **一、Lombok 是什么** Lombok 是一款小巧的代码生成工具。官方网址:[http://projectlombok.org/](https://gitee.com/vip204888/java-p7) 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` 已经存在。 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429125233811.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://gitee.com/vip204888/java-p7)内省机制(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); } } ``` [](https://gitee.com/vip204888/java-p7)apache的 commons 项目(了解) ========================================================================================= 这部分内容了解一下就可以,知道 apache 有很多强大的项目,commons 是其中之一。 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429130937630.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://gitee.com/vip204888/java-p7)JavaBean 和 Map 相互转换(自行实现) -------------------------------------------------------------------------------------------- * JavaBean 拥有**多组属性名和属性值**,每一个属性名称对应一个属性值,属性名称不同。 * Map 拥有**多组 key-value**,每一个 key 对应一个 value,key 不同。 如果把 JavaBean 中的属性名称看做是 Map 中的 key,二者就是等价的。 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429130546705.png) 把 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; } } ``` [](https://gitee.com/vip204888/java-p7)commons-beanutils(了解、体验一下使用即可) ------------------------------------------------------------------------------------------------- 这部分了解一下即可,大概体验一下这些工具类的作用。。。 需要 jar 包:`commons-beanutils-1.9.4.jar`、`commons-logging-1.2.jar`; ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429132609380.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) ``` 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; ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429132109721.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429132201282.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) **日期类转换的细节**:beanutils 不支持 String --> Date 转换,需要手动设置转换模式。 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429132344245.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://gitee.com/vip204888/java-p7)注解(Annotation) ================================================================================= [](https://gitee.com/vip204888/java-p7)初始注解 ----------------------------------------------------------------------- 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代码); ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429133753909.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://gitee.com/vip204888/java-p7)JDK自带的注解 --------------------------------------------------------------------------- * `@Override`:限定覆写父类方法 * `@Deprecated`:标记已过时不推荐使用 在 JDK1.5 之前,使用文档注释来标记过时 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429134225632.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) * `@SuppressWarings`:抑制编译器发出的警告 `@SuppressWarings(value="all")` * `@SafeVarargs`:抑制堆污染警告(Java7开始出现的) 该注解仅仅是抑制住编译器不要报警告,但是存在的风险依然存在。 使用注解存在的疑惑: 1. 为什么有的注解可以贴在类上/方法上/变量上,而有些却不行? 肯定有东西来约束注解贴的位置。 2. 为什么有的注解可以接受参数,比如`@SuppressWarings(value="all")`,而有的注解却不行。 通过查看注解的源代码,发现**注解中存在抽象方法才可以使用参数**。 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429134725456.png) [](https://gitee.com/vip204888/java-p7)元注解(@Retention、@Target、@Documented、@Inherited) ----------------------------------------------------------------------------------------------------------------- 元注解:**注解的元数据** —> 定义注解时,注解上的注解。 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429135006272.png) `@Retention`: **表示注解可以保存在哪一个时期**;保存的时期的值,封装在 `RetentionPolicy` 枚举类中;一般自定义的注解,使用`RUNTIME`(使用反射赋予注解功能) * `SOURCE`:注解只能存在于**源文件**中,编译之后,字节码文件中没有。 * `CLASS`: 注解可以存在于**源文件和字节码文件**中,无法加载进 JVM。 * `RUNTIME`:注解可以存在于**源文件,字节码文件,JVM** 中。 ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429135252635.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) `@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{} ``` [](https://gitee.com/vip204888/java-p7)注解的定义和使用 --------------------------------------------------------------------------- 注解的定义语法: ``` @Target(ElementType.TYPE) // 标识该注解可以贴在类上/接口上 @Retention(RetentionPolicy.RUNTIME) // 标识该注解可以存在于JVM中(通过反射赋予功能) public @interface 注解名称 { // 抽象方法-->属性 返回类型 方法名称() default 值; ... } ``` 注意:注解中 **抽象方法(属性)** 类型 * 只能是 基本类型、`String`、`Class`、`annotation`、枚举 、数组 * 当只有一个属性并且名称为 value,此时可以省略 value ``` // @VIP(value="xx") @VIP("xx") // 可以省略value public class Employee {} ``` 注解到底有什么用: **取代繁琐、臃肿的配置文件** * 如果没有注解: 学习 Servlet 做配置,需要在 XML 文件中写8行代码 * 使用注解: 学习 Servlet 的时候,只需要在 Servlet 类上标注:`@WebServlet("/abc")` 自定义一个注解 `@VIP`: ``` import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) // 标识该注解可以贴在类上/接口上 @Retention(RetentionPolicy.RUNTIME) // 标识该注解可以存在于JVM中(通过反射赋予功能) public @interface VIP { String value(); int age() default 18; // 使用时可以省略, 默认值是18 String [] hobby() default {"Python", "html"}; // 使用时可以省略 } ``` 使用上面定义的 `@VIP` 注解: ``` // 注解中有default的是可以省略的 //@VIP(value="xx") 这么写相当于 @VIP(value="xx",age=18,hobby={"python,html"}) @VIP(value="xx",age=20,hobby={"Java","C++"}) public class Person {} ``` [](https://gitee.com/vip204888/java-p7)获取程序元素上的注解 ----------------------------------------------------------------------------- 注解可以贴在类(Class)、方法(Method)、字段(Field)、构造器(Constructor)上等; 所以在 `Class`、`Method`、`Field`、`Contructor` 类中就拥有获取注解的API; ``` "如果存在该元素的指定类型的注解, 则返回这些注解, 否则返回 null" Annotation getAnnotation(Class annotationClass)
“返回此元素上存在的所有注解”
Annotation[] getAnnotations()
"判断当前成员上是否标注了某一个注解" boolean isAnnotationPresent(Class annotationClass) ``` 例:获取 Person上所有的注释; ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429143829329.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) 例:判断 Person 类上是否有 `@VIP` 注解; ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429144514745.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://gitee.com/vip204888/java-p7)模拟 junit4.x ------------------------------------------------------------------------------ 模拟 `@Before` 写一个 `@MyBefore`: ``` @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyBefore {} ``` 模拟 `@After` 写一个 `@MyAfter`: ``` @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAfter {} ``` ## 总结 > 这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额! 某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功! 成功只会留给那些有准备的人![**资料免费领取方式:戳这里**](https://gitee.com/vip204888/java-p7) NQ==,size_16,color_FFFFFF,t_70) 例:判断 Person 类上是否有 `@VIP` 注解; ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429144514745.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://gitee.com/vip204888/java-p7)模拟 junit4.x ------------------------------------------------------------------------------ 模拟 `@Before` 写一个 `@MyBefore`: ``` @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyBefore {} ``` 模拟 `@After` 写一个 `@MyAfter`: ``` @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAfter {} ``` ## 总结 > 这份面试题几乎包含了他在一年内遇到的所有面试题以及答案,甚至包括面试中的细节对话以及语录,可谓是细节到极致,甚至简历优化和怎么投简历更容易得到面试机会也包括在内!也包括教你怎么去获得一些大厂,比如阿里,腾讯的内推名额! 某位名人说过成功是靠99%的汗水和1%的机遇得到的,而你想获得那1%的机遇你首先就得付出99%的汗水!你只有朝着你的目标一步一步坚持不懈的走下去你才能有机会获得成功! 成功只会留给那些有准备的人![**资料免费领取方式:戳这里**](https://gitee.com/vip204888/java-p7) ![](https://ucc.alicdn.com/images/user-upload-01/img_convert/b09fc118e9472934d3bc21c0200d0e5d.png)