注解和反射

1. 注解

注解作用:

  • 对程序做出解释
  • 被其他程序读取

注解格式:

  • @注释名,还可以添加一些参数值,例如@SuppressWarnings(value="unchecked").

注解使用在哪里

可以附加在package,class,method,filed,上面,相当于添加了额外的辅助信息,可以通过反射机制对这些元数据进行访问

内置注解

1. @Override

该注释只用于修饰方法,表示重写超类的一个方法,可以让让编译器检查该方法是否正确地实现了覆写

2. Deprecated

该注释可以用于修饰方法、属性、类,表示不鼓励使用,因为使用存在危险或有更好的选择

3. @SuppresseWarnings("para")

告诉编译器忽略此处代码产生的警告,需要参数才能正确的使用,例如 @SuppresseWarnings("all"),

@SuppresseWarnings("unchecked"), @SuppresseWarnings(value={"unchecked","deprecation"})

  1. package com.annotation;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. public class TestAnnotation {
  5. //override 方法重写注解
  6. @Override
  7. public String toString() {
  8. return super.toString();
  9. }
  10. //Deprecated 不推荐使用,但是任然可以使用
  11. @Deprecated
  12. public static void test(){
  13. System.out.println("test");
  14. }
  15. //SuppressWarnings(" ")忽视警告,可以放在方法上
  16. @SuppressWarnings("all")
  17. public void test01(){
  18. List list = new ArrayList();
  19. }
  20. }

元注解

元注解用于解释其他注解

@Target

表示注解使用范围

  • 类或接口:ElementType.TYPE
  • 字段:ElementType.FIELD
  • 方法:ElementType.METHOD
  • 构造方法:ElementType.CONSTRUCTOR
  • 方法参数:ElementType.PARAMETER

@Retention

Retention 定义了Annotation的生命周期

  • 仅编译期:RetentionPolicy.SOURCE
  • 仅class文件:RetentionPolicy.CLASS
  • 运行期:RetentionPolicy.RUNTIME

如果@Retention不存在,则该Annotation默认为CLASS。因为通常我们自定义的Annotation都是RUNTIME,所以,务必要加上@Retention(RetentionPolicy.RUNTIME)这个元注解

@Inherited

使用@Inherited定义子类是否可继承父类定义的Annotation@Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效,并且仅针对class的继承,对interface的继承无效

@Documented

表明该注解将被包含于javadoc内

  1. public class TestMetaAnnotation {
  2. @MyAnnotation
  3. public void testMetaAnnotation(){
  4. }
  5. }
  6. //定义一个元注解
  7. //Target 表示注解使用范围
  8. @Target(value = ElementType.METHOD)
  9. //Retention 定义了Annotation的生命周期
  10. // runtime>class>source
  11. @Retention(value = RetentionPolicy.RUNTIME)
  12. //表明该注解将被包含于javadoc内
  13. @Documented
  14. //子类可以继承父类的注解
  15. @Inherited
  16. @interface MyAnnotation{
  17. }

自定义注解@interface

使用@interface自动继承Annotation接口

  1. public class TestCreateAnnotation {
  2. @MyAnnotation02(name = "",age = 10)
  3. public void test(){
  4. }
  5. @MyAnnotation03("Fuck") //只有一个参数时直接赋值
  6. public void test03(){
  7. }
  8. }
  9. //创建注解
  10. @Target({ElementType.TYPE,ElementType.METHOD})
  11. @interface MyAnnotation02{
  12. //注解参数 : paraType paraName() |(default value);
  13. String name() default ""; //如果不设置默认值,使用注解时必须给参数赋值
  14. int age(); //使用时必须赋值
  15. int id() default -1; //default -1 表示默认不存在
  16. String[] school() default {"Tsinghua","Peking"};
  17. }
  18. @Target({ElementType.TYPE,ElementType.METHOD})
  19. @Retention(RetentionPolicy.RUNTIME)
  20. @interface MyAnnotation03{
  21. String value(); //只有一个参数成员时,参数名一般为value
  22. }

2.反射

3.1 反射机制

  • 反射机制允许程序在运行期间借助与Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性以及方法
  • 加载完类后,在堆内存的方法区产生了一个Class类型的对象,这个对象包含了完整的类的结构信息,我们可以通过这个对象看到类的结构

  • 反射实现了语言的动态创建和编译,具有很大的灵活性
  • 反射机制是一种解释型的操作,执行效率较低

3.2 Class类

Class类的常用方法

获取类的Class对象

  1. 对于已知的类,直接通过类的class对象获取,该方法最为可靠,性能最好

    1. Class clz = Cls.class;
  2. 对于某个实例,调用getClass方法获取

    1. Class clz = cls.getClass();
  3. 通过类的路径以及类名,调用Class类的静态方法forName方法获取

    1. Class clz = forName("packegePath.className");
  4. 内置基本数据类型直接使用 className.Type获取

  5. ClassLoader获取

  1. //获取Class类对象
  2. public class TestGetClassInstance {
  3. public static void main(String[] args) throws ClassNotFoundException {
  4. Person person = new Person();
  5. System.out.println("He is "+person.name);
  6. Person s1 = new Student();
  7. Class cs = s1.getClass();
  8. //通过类名直接获取
  9. Class c1 = Person.class;
  10. System.out.println(c1.hashCode());
  11. //forName 方法获取
  12. Class c2 = Class.forName("com.Reflection.Demo01.Person");
  13. System.out.println(c2.hashCode());
  14. //实例.getClass()方法获取
  15. Class c3 = person.getClass();
  16. System.out.println(c3.hashCode()); //c1 ~ c3 The same HashCode
  17. // 基本内置类型的包装类的Type属性
  18. Class c4 = Integer.TYPE;
  19. System.out.println(c4);
  20. //获得父类类型(实际类型)
  21. Class c5 = cs.getSuperclass();
  22. System.out.println(c5);
  23. }
  24. }
  25. class Person{
  26. public String name;
  27. public Person() {
  28. }
  29. @Override
  30. public String toString() {
  31. return "Person{" +
  32. "name='" + name + '\'' +
  33. '}';
  34. }
  35. }
  36. class Student extends Person{
  37. public Student() {
  38. this.name="Student";
  39. }
  40. }
  41. class Teacher extends Person{
  42. public Teacher() {
  43. this.name = "Teacher";
  44. }
  45. }

拥有Class类型的对象

  1. public class TestClassesPossessedClassAttribute {
  2. public static void main(String[] args) {
  3. Class c1 = Object.class; //类
  4. Class c2 = Comparable.class; //接口
  5. Class c3 = String[].class; //一维数组
  6. Class c4 = int[][].class; //二维
  7. Class c5 = Override.class; //注解
  8. Class c6 = ElementType.class; //枚举
  9. Class c7 = Integer.class; //基本数据类型
  10. Class c8 = void.class; //void
  11. Class c9 = Class.class; //Class
  12. //alt+鼠标左键选中一列数据
  13. System.out.println(c1);
  14. System.out.println(c2);
  15. System.out.println(c3);
  16. System.out.println(c4);
  17. System.out.println(c5);
  18. System.out.println(c6);
  19. System.out.println(c7);
  20. System.out.println(c8);
  21. System.out.println(c9);
  22. //只要元素的类型与维度一样,就是同一个class
  23. int[] a = new int[10];
  24. int[] b = new int[100];
  25. System.out.println(a.getClass().hashCode()); //Same HashCode
  26. System.out.println(b.getClass().hashCode());

类加载过程

  1. public class TestLoadClass {
  2. public static void main(String[] args) {
  3. A a = new A();
  4. System.out.println(A.m);
  5. /*
  6. 1.加载到内存,生成类的Class对象
  7. A.class;TestLoadClass.class;
  8. 2.链接,为类变量分配内存和赋初值
  9. m=0;
  10. 3.初始化
  11. 执行类构造器方法<clinit>()将所有类变量赋值以及静态代码块合并形成
  12. <clinit>(){
  13. static {
  14. System.out.println("Static Filed");
  15. m = 200;
  16. }
  17. static int m= 100;
  18. }
  19. */
  20. }
  21. }
  22. class A{
  23. static {
  24. System.out.println("Static Filed");
  25. m = 200;
  26. }
  27. /*
  28. m=200;
  29. m=100
  30. */
  31. static int m= 100;
  32. public A(){
  33. System.out.println("A类的无参构造初始化");
  34. }
  35. }

类的初始化

  1. public class TestInitClass {
  2. static {
  3. //1.main方法所在类初始化
  4. System.out.println("buying a gun");
  5. }
  6. public static void main(String[] args) throws ClassNotFoundException {
  7. //2.主动引用new
  8. //Robber robber = new Robber();
  9. //3.反射引用
  10. //Class.forName("com.Reflection.Demo01.Robber");
  11. //不会产生类的初始化
  12. //1.调用子类继承父类的静态变量和方法时
  13. //System.out.println(Robber.moneyBefore);
  14. //Robber.b();
  15. //2.初始化类的数组时
  16. Robber[] robbers = new Robber[10];
  17. //3.引用常量(链接阶段就存入调用类的常量池了)
  18. System.out.println(Robber.escapeMoney);
  19. }
  20. }
  21. //测试类初始化
  22. class Criminal{
  23. static double moneyBefore = 20;
  24. static {
  25. System.out.println("Gives me your fucking money!");
  26. }
  27. static void b(){
  28. System.out.println("父类静态方法调用");
  29. }
  30. }
  31. class Robber extends Criminal{
  32. static {
  33. System.out.println("This is a robbery! Put your hands up!!");
  34. double getMoney = 292898;
  35. }
  36. static double robberMoney = 8361303.222;
  37. static final double escapeMoney = 1000;
  38. }

类加载器作用

双亲委派机制

当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个操作,如果上级的类加载器没有加载,自己才会去加载这个类。

  1. public class TestClassLoader {
  2. public static void main(String[] args) {
  3. //获取系统类加载器
  4. ClassLoader classLoader = ClassLoader.getSystemClassLoader();
  5. System.out.println(classLoader);
  6. // 获取系统类加载器父类---扩展类加载器
  7. classLoader = classLoader.getParent();
  8. System.out.println(classLoader);
  9. // 获取扩展类加载器父类---根加载器(无法获取:null)
  10. classLoader = classLoader.getParent();
  11. System.out.println(classLoader);
  12. //测试当前类的ClassLoader
  13. classLoader = TestLoadClass.class.getClassLoader();
  14. System.out.println(classLoader);
  15. //测试JDK内置类的加载器
  16. classLoader = String.class.getClassLoader();
  17. System.out.println(classLoader);
  18. //获得系统类加载器路径
  19. System.out.println(System.getProperty("java.class.path"));
  20. }
  21. }

3.3 反射操作

1. 获取类的结构

  1. package com.reflection.Demo02;
  2. import java.lang.reflect.Constructor;
  3. import java.lang.reflect.Field;
  4. import java.lang.reflect.Method;
  5. //Testing using the class object to obtain the contents of a class
  6. public class TestGetClassInfo {
  7. public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
  8. // Get the Class of a class by path
  9. Class c1 = Class.forName("com.reflection.Demo01.User");
  10. //Get ClassName
  11. System.out.println(c1.getName()); //package + ClassName
  12. System.out.println(c1.getSimpleName()); //ClassName
  13. System.out.println();
  14. //Get all public properties
  15. Field[] fields = c1.getFields(); //getField() only used on properties with decoration of public
  16. for (Field field : fields) { //out: null ,no method decorated with public
  17. System.out.println(field);
  18. }
  19. //Get all properties
  20. fields = c1.getDeclaredFields(); //getDeclaredFields() used on all types of properties
  21. for (Field field : fields) {
  22. System.out.println(field);
  23. }
  24. System.out.println();
  25. //Get particular property
  26. //only public
  27. //Field name = c1.getField("name"); -> NoSuchFieldException
  28. //out.println(name);
  29. Field name = c1.getDeclaredField("name");
  30. System.out.println(name);
  31. System.out.println();
  32. //Get methods
  33. Method[] methods = c1.getMethods();//all public methods include methods inherited superClass or superInterface
  34. for (Method method : methods) {
  35. System.out.println(method);
  36. }
  37. System.out.println();
  38. methods = c1.getDeclaredMethods();
  39. for (Method method : methods) { //all methods exclude inherited
  40. System.out.println(method);
  41. }
  42. System.out.println();
  43. //Get particular method getMethod(name,paraType.class)
  44. Method method1 =c1.getMethod("getName",null);
  45. Method method2 =c1.getMethod("setName",String.class);
  46. System.out.println(method1);
  47. System.out.println(method2);
  48. System.out.println();
  49. //Get Constructors
  50. Constructor[] constructors = c1.getConstructors();
  51. for (Constructor constructor : constructors) { //public constructors
  52. System.out.println(constructor);
  53. }
  54. System.out.println();
  55. constructors = c1.getDeclaredConstructors();
  56. for (Constructor constructor : constructors) {//all
  57. System.out.println(constructor);
  58. }
  59. System.out.println();
  60. //get particular public constructor getConstructor(para.class|null);
  61. Constructor constructor = c1.getConstructor(String.class);
  62. System.out.println(constructor);
  63. System.out.println();
  64. //get particular constructor getDeclaredConstructor(para.class|null);
  65. constructor = c1.getDeclaredConstructor(String.class);
  66. System.out.println(constructor);
  67. constructor = c1.getDeclaredConstructor(null);
  68. System.out.println(constructor);
  69. }
  70. }

获取父类:getSuperclass()

获取继承的接口:getInterfaces()

如果是两个Class实例,要判断一个向上转型是否成立,可以调用isAssignableFrom()

2.反射创建对象

方法1:Class.newInstance() 方法(java9后弃用)

  1. //获取对象
  2. Class c1 = User.class;
  3. //构造一个对象
  4. User user = (User)c1.newInstance();
  5. System.out.println(user);

局限:它只能调用该类的public无参数构造方法。

方法2:通过构造器对象newInstance()方法创建对象

  1. Constructor constructor = c1.getDeclaredConstructor(String.class,String.class,int.class,String.class);
  2. User user2 = (User)constructor.newInstance("001","wang",20,"Male");
  3. System.out.println(user2);

调用非publicConstructor时,必须首先通过setAccessible(true)设置允许访问。

3.反射调用方法

  1. Method sN = c1.getDeclaredMethod("setName",String.class);
  2. sN.invoke(user2,"Liu");//method.invoke(obj,value)
  3. System.out.println(user2.getName());

method对象包含信息

  • getName():返回方法名称,例如:"getScore"
  • getReturnType():返回方法返回值类型,也是一个Class实例,例如:String.class
  • getParameterTypes():返回方法的参数类型,是一个Class数组,例如:{String.class, int.class}
  • getModifiers():返回方法的修饰符,它是一个int,不同的bit表示不同的含义。

如果获取到的Method表示一个静态方法,调用静态方法时,由于无需指定实例对象,所以invoke方法传入的第一个参数永远为null

调用非public方法,我们通过Method.setAccessible(true)允许其调用:

4.设置字段值

  1. Field name= c1.getDeclaredField("name");
  2. name.setAccessible(true); //不能直接操作私有属性,需要设置访问安全检查为true
  3. name.set(user2,"Li"); //field.set(fieldObj,value)
  4. System.out.println(user2.getName());

一个Field对象包含了一个字段的所有信息:

  • getName():返回字段名称,例如,"name"
  • getType():返回字段类型,也是一个Class实例,例如,String.class
  • getModifiers():返回字段的修饰符,它是一个int,不同的bit表示不同的含义。

修改非public字段,需要首先调用setAccessible(true)

5.SetAccessible

  1. public class TestSetAcc {
  2. public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
  3. User user = new User();
  4. long start = System.currentTimeMillis();
  5. for (int i = 0; i < 1_000_000_000; i++) {
  6. user.getName();
  7. }
  8. long end = System.currentTimeMillis();
  9. System.out.println("普通方式调用方法十亿次"+(end-start)+"ms");
  10. //反射方式
  11. TestSetAcc.test();
  12. TestSetAcc.test01();
  13. }
  14. public static void test() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
  15. Class c1 = User.class;
  16. User user = new User();
  17. Method method= c1.getDeclaredMethod("getName",null);
  18. method.setAccessible(true);
  19. long start = System.currentTimeMillis();
  20. for (int i = 0; i < 1_000_000_000; i++) {
  21. method.invoke(user,null);
  22. }
  23. long end = System.currentTimeMillis();
  24. System.out.println("关闭检测方式调用十亿次"+(end-start)+"ms");
  25. }
  26. public static void test01() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
  27. Class c1 = User.class;
  28. User user = new User();
  29. Method method= c1.getDeclaredMethod("getName",null);
  30. method.setAccessible(false);
  31. long start = System.currentTimeMillis();
  32. for (int i = 0; i < 1_000_000_000; i++) {
  33. method.invoke(user,null);
  34. }
  35. long end = System.currentTimeMillis();
  36. System.out.println("检测方式调用十亿次"+(end-start)+"ms");
  37. }
  38. }

6.反射操作泛型

  1. //反射获取泛型
  2. public class TestReflectionGeneric {
  3. public void test01(Map<String,User> map, List<User> list){
  4. System.out.println("Test01");
  5. }
  6. public Map<String,User> test02(){
  7. System.out.println("Test02");
  8. return null;
  9. }
  10. public static void main(String[] args) throws NoSuchMethodException {
  11. Method method = TestReflectionGeneric.class.getDeclaredMethod("test01",Map.class,List.class);
  12. Type[] genericParameterTypes= method.getGenericParameterTypes();
  13. for (Type genericParameterType : genericParameterTypes) {
  14. System.out.println(genericParameterType);
  15. if(genericParameterType instanceof ParameterizedType){
  16. Type[] actualTypeArguments= ((ParameterizedType) genericParameterType).getActualTypeArguments();
  17. for (Type actualTypeArgument : actualTypeArguments) {
  18. System.out.println(actualTypeArgument);
  19. }
  20. }
  21. }
  22. System.out.println();
  23. Method method01 = TestReflectionGeneric.class.getDeclaredMethod("test02",null);
  24. Type genericReturnTypeType = method01.getGenericReturnType();
  25. if(genericReturnTypeType instanceof ParameterizedType){
  26. Type[] actualTypeArguments= ((ParameterizedType) genericReturnTypeType).getActualTypeArguments();
  27. for (Type actualTypeArgument : actualTypeArguments) {
  28. System.out.println(actualTypeArgument);
  29. }
  30. }
  31. }
  32. }

7.反射操作注解

  1. //反射操作注解
  2. public class TestReflectionAnnotation {
  3. public static void main(String[] args) throws NoSuchFieldException {
  4. //反射获得类的注解
  5. Class c1 = Student.class;
  6. Annotation[] annotations = c1.getAnnotations();
  7. for (Annotation annotation : annotations) {
  8. System.out.println(annotation);
  9. }
  10. //获得注解的value
  11. Table table = (Table) c1.getAnnotation(Table.class);
  12. System.out.println(table.value());
  13. //获得指定注解
  14. Field field = c1.getDeclaredField("id");
  15. FieldAnn annotation = field.getAnnotation(FieldAnn.class);
  16. System.out.println(annotation.columnName());
  17. System.out.println(annotation.type());
  18. System.out.println(annotation.length());
  19. }
  20. }
  21. @Table("TableStudent")
  22. class Student{
  23. @FieldAnn(type = "varchar",length = 10,columnName = "db_id")
  24. private String id;
  25. @FieldAnn(type = "db_int",length = 10,columnName = "db_age")
  26. private int age ;
  27. @FieldAnn(type = "varchar",length = 10,columnName = "dn_name")
  28. private String name;
  29. public Student() {
  30. }
  31. public String getId() {
  32. return id;
  33. }
  34. public void setId(String id) {
  35. this.id = id;
  36. }
  37. public int getAge() {
  38. return age;
  39. }
  40. public void setAge(int age) {
  41. this.age = age;
  42. }
  43. public String getName() {
  44. return name;
  45. }
  46. public void setName(String name) {
  47. this.name = name;
  48. }
  49. }
  50. //class annotation
  51. @Target(ElementType.TYPE)
  52. @Retention(RetentionPolicy.RUNTIME)
  53. @interface Table{
  54. String value();
  55. }
  56. //field annotation
  57. @Target(ElementType.FIELD)
  58. @Retention(RetentionPolicy.RUNTIME)
  59. @interface FieldAnn{
  60. String columnName();
  61. String type();
  62. int length();
  63. }

Java学习笔记--注解和反射的更多相关文章

  1. 0035 Java学习笔记-注解

    什么是注解 注解可以看作类的第6大要素(成员变量.构造器.方法.代码块.内部类) 注解有点像修饰符,可以修饰一些程序要素:类.接口.变量.方法.局部变量等等 注解要和对应的配套工具(APT:Annot ...

  2. Java学习笔记之使用反射+泛型构建通用DAO

    PS:最近简单的学了学后台Servlet+JSP.也就只能学到这里了.没那么多精力去学SSH了,毕竟Android还有很多东西都没学完.. 学习内容: 1.如何使用反射+泛型构建通用DAO. 1.使用 ...

  3. Java学习笔记54(反射详解)

    反射概念: java反射机制是在运行状态中,对于任意一个类,都能知道所有属性和方法 对于任意一个对象都能调用它的任意一个方法和属性,这种动态获取和调用的功能称为java的反射机制 实际作用: 已经完成 ...

  4. Java学习笔记八(反射)

    1.介绍 反射为Java程序在执行时提供了动态的能力.利用反射能够在执行时对程序进行动态的控制.本篇博客着重解说一下Java中的反射. 2.Class类的使用 在Java执行过程中,每一个类被载入后都 ...

  5. Java学习笔记--注解

    注解的使用与实例:http://www.cnblogs.com/pepcod/archive/2013/02/16/2913474.html 注解的作用及使用方法:http://wenku.baidu ...

  6. Java学习:注解,反射,动态编译

    狂神声明 : 文章均为自己的学习笔记 , 转载一定注明出处 ; 编辑不易 , 防君子不防小人~共勉 ! Java学习:注解,反射,动态编译 Annotation 注解  什么是注解 ? Annotat ...

  7. JAVA学习笔记—review基本知识[反射与异常]

    JAVA学习笔记—review基本知识[反射与异常] 1.异常: 1.1异常的分类: Java会将所有的异常封装成对象,其根本父类为Throwable. Throwable有两个子类:Error 和E ...

  8. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  9. 0032 Java学习笔记-类加载机制-初步

    JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...

随机推荐

  1. HCIA-物理层

    OSI七层模型 应-->表-->会-->传-->网-->数-->物理层 TCP/IP四层模型 两个主导协议 -->工业标准 应-->传-->网-- ...

  2. 在Ubuntu下的OpenStack中配置使用Spice协议

    在Ubuntu下的OpenStack中配置使用Spice协议 by 无若 ####控制节点#安装apt-get install nova-spiceproxy spice-html5 spice-vd ...

  3. 【Java】jeesite初始配置以及代码生成工具的使用

    jeesite简单使用 首先去技术服务与支持.版本区别一览表 - JeeSite 4.x找到源码下载的部分 JeeSite 源码下载:https://gitee.com/thinkgem/jeesit ...

  4. Java JVM【笔记】

    Java JVM[笔记] Java的平台无关性是如何实现的? Java源码首先被编译成字节码,再由不同的平台的JVM进行解析,Java语言在不同的平台上运行时不需要进行重新编译,Java虚拟机在执行字 ...

  5. IDEA spring boot项目插件打包方式jar

    一.打包 1.pom.xml中添加插件依赖 <build> <plugins> <plugin> <!--打包成可执行jar--> <groupI ...

  6. Django 反向解析 request CBV

    正则路径中的分组 无名分组 分组的概念:就是给某一段正则表达式用小括号括起来 无名分组按位置传参数,一一对应. view中除去request,其他形参数量要与urls中分组数量一致. 无名分组就是将括 ...

  7. 当Atlas遇见Flink——Apache Atlas 2.2.0发布!

    距离上次atlas发布新版本已经有一年的时间了,但是这一年元数据管理平台的发展一直没有停止.Datahub,Amundsen等等,都在不断的更新着自己的版本.但是似乎Atlas在元数据管理,数据血缘领 ...

  8. docker 安装mysql设置不区分表名大小写,创建minio,设置开机自启动

    环境deepin mysql : docker run -p 3306:3306 --name tyer-mysql --restart=always -v $PWD/conf:/etc/mysql/ ...

  9. Future有返回值的线程

    //创建一个线程池 ExecutorService pool = Executors.newFixedThreadPool(100); //创建多个有返回值的任务 List<Future> ...

  10. Asp.NetCore 中Aop的应用

    前言 其实好多项目中,做一些数据拦截.数据缓存都有Aop的概念,只是实现方式不一样:之前大家可能都会利用过滤器来实现Aop的功能,如果是Asp.NetCore的话,也可能会使用中间件: 而这种实现方式 ...