J2EE知识点总结_Java常用类

简介: J2EE知识点总结_Java常用类

Java常用类

字符串相关的类

String的特性

  • String是一个final类,代表不可变的字符序列。
  • 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
  • String对象的字符内容是存储在一个字符数组value[]中的。

String str1 = “abc”;与String str2 = new String(“abc”);的区别?

String str1 = “abc”;字符串常量存储在 字符串常量池,目的是共享

String str2 = new String(“abc”);字符串非常量对象存储在堆中

字符串对象是如何存储的?

  • 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
  • 只要其中有一个是变量,结果就在堆中
  • 如果拼接的结果调用intern()方法,返回值就在常量池中

a88b52a0ba36479b8affa171f7f1b937.png

String常用方法

int length():返回字符串的长度: return value.length
char charAt(int index): 返回某索引处的字符return value[index]
boolean isEmpty():判断是否是空字符串:return value.length == 0
String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写
String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写
String trim():返回字符串的副本,忽略前导空白和尾部空白
boolean equals(Object obj):比较字符串的内容是否相同
boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
int compareTo(String anotherString):比较两个字符串的大小
String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
注:indexOf和lastIndexOf方法如果未找到都是返回-1
String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
String replaceAll(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
String replaceFirst(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中

StringBuffer类

java.lang.StringBuffer代表可变的字符序列,JDK1.0中声明,可以对字符 串内容进行增删,此时不会产生新的对象。

StringBuffer类不同于String,其对象必须使用构造器生成。有三个构造器:

  • StringBuffer():初始容量为16的字符串缓冲区
  • StringBuffer(int size):构造指定容量的字符串缓冲区
  • StringBuffer(String str):将内容初始化为指定字符串内容

StringBuffer类的常用方法

StringBuffer append(xxx):提供了很多的append()方法,用于进行字符串拼接
StringBuffer delete(int start,int end):删除指定位置的内容
StringBuffer replace(int start, int end, String str):把[start,end)位置替换为str
StringBuffer insert(int offset, xxx):在指定位置插入xxx
StringBuffer reverse() :把当前字符序列逆转
public int indexOf(String str)
public String substring(int start,int end)
public int length()
public char charAt(int n )
public void setCharAt(int n ,char ch)

当append和insert时,如果原来value数组长度不够,可扩容

StringBuilder类

  • StringBuilder 和 StringBuffer 非常类似,均代表可变的字符序列,而且 提供相关功能的方法也一样

面试题:对比String、StringBuffer、StringBuilder

  • String(JDK1.0):不可变字符序列
  • StringBuffer(JDK1.0):可变字符序列、效率低、线程安全
  • StringBuilder(JDK 5.0):可变字符序列、效率高、线程不安全

注意:作为参数传递的话,方法内部String不会改变其值,StringBuffer和StringBuilder 会改变其值。

测试三者的效率:

    /*
    对比String、StringBuffer、StringBuilder三者的效率:
    从高到低排列:StringBuilder > StringBuffer > String
     */
public class StringBuilderTest {
    public static void main(String[] args) {
        long startTime = 0L;
        long endTime = 0L;
        StringBuffer buffer = new StringBuffer("");
        StringBuilder builder = new StringBuilder("");
        String str = "";
        //StringBuffer的执行时间
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            buffer.append(String.valueOf(i));
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuffer的执行时间:" + (endTime - startTime));//StringBuffer的执行时间:3
        //StringBuilder的执行时间
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            builder.append(String.valueOf(i));
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuilder的执行时间:" + (endTime - startTime));//StringBuilder的执行时间:3
        //String的测试时间
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            str = str + i;
        }
        endTime = System.currentTimeMillis();
        System.out.println("String的测试时间:" + (endTime - startTime));//String的测试时间:908
    }
}    
String、StringBuffer、StringBuilder三者的异同?
  String:不可变的字符序列;底层使用char[]存储
    StringBuffer:可变的字符序列;线程安全的,效率低;底层使用char[]存储
    StringBuilder:可变的字符序列;jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储
    源码分析:
    String str = new String();//char[] value = new char[0];
    String str1 = new String("abc");//char[] value = new char[]{'a','b','c'};
    StringBuffer sb1 = new StringBuffer();//char[] value = new char[16];底层创建了一个长度是16的数组。
    System.out.println(sb1.length());//
    sb1.append('a');//value[0] = 'a';
    sb1.append('b');//value[1] = 'b';
    StringBuffer sb2 = new StringBuffer("abc");//char[] value = new char["abc".length() + 16];
    //问题1. System.out.println(sb2.length());//3
    //问题2. 扩容问题:如果要添加的数据底层数组盛不下了,那就需要扩容底层的数组。
             默认情况下,扩容为原来容量的2倍 + 2,同时将原有数组中的元素复制到新的数组中。
            指导意义:开发中建议大家使用:StringBuffer(int capacity) 或 StringBuilder(int capacity)

日期时间API

java.util.Date类 表示特定的瞬间,精确到毫秒

  • Date():使用无参构造器创建的对象可以获取本地当前时间
  • getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象 表示的毫秒数。
    @Test
    public void test2() {
        Date date = new Date();
        System.out.println(date);//Mon Oct 03 20:44:17 CST 2022
        System.out.println(date.getTime());//返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数1664804213645
        System.out.println(date.getMonth());//9
    }

java.text.SimpleDateFormat类

  • Date类的API不易于国际化,大部分被废弃了,java.text.SimpleDateFormat 类是一个不与语言环境有关的方式来格式化和解析日期的具体类
    @Test
    public void test3() {
        //日期-->文本的格式化
        // 产生一个Date实例
        Date date = new Date();
        // 产生一个 simpleDateFormat 格式化的实例
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        System.out.println(simpleDateFormat.format(date));//22-10-3 下午9:41
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy年MM月dd日 EEE HH:mm:ss");
        System.out.println(simpleDateFormat1.format(date));//2022年10月03日 星期一 21:42:58
        //文本-->日期的格式化
        try {
            // 实例化一个指定的格式对象
            Date date1 = simpleDateFormat1.parse("2008年08月08日 星期一 08:08:08");
            // 将指定的日期解析后格式化按指定的格式输出
            System.out.println(date1);//Fri Aug 08 08:08:08 CST 2008
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

java.util.Calendar(日历)类

Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能

获取Calendar实例的方法

  • 使用Calendar.getInstance()方法
  • 调用它的子类GregorianCalendar的构造器

Java比较器(对象比较排序)

Java实现对象排序的方式有两种:

1 自然排序:java.lang.Comparable

Comparable 的典型实现:(默认都是从小到大排列的)

  • String:按照字符串中字符的Unicode值进行比较
  • Character:按照字符的Unicode值来进行比较
  • 数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值 大小进行比较
  • Boolean:true 对应的包装类实例大于 false 对应的包装类实例
  • Date、Time等:后面的日期时间比前面的日期时间大
package com.jerry.java;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
/**
 * @author jerry_jy
 * @create 2022-10-04 8:53
 */
public class ComparableTest {
    public static void main(String[] args) {
        Goods[] all = new Goods[4];
        all[0] = new Goods("《红楼梦》", 100);
        all[1] = new Goods("《西游记》", 80);
        all[2] = new Goods("《三国演义》", 140);
        all[3] = new Goods("《水浒传》", 120);
        Arrays.sort(all);
        System.out.println(Arrays.toString(all));
    }
}
class Goods implements Comparable {
    private String name;
    private double price;
    public Goods() {
    }
    public Goods(String name, double price) {
        this.name = name;
        this.price = price;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Goods{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
    //指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从高到低排序
    @Override
    public int compareTo(Object o) {
        if (o instanceof Goods) {
            Goods goods = (Goods) o;
//            if (this.price > goods.price) {
//                return 1;
//            } else if (this.price < goods.getPrice()) {
//                return -1;
//            }else {
//                return 0;
//            }
            //方式二:
           return Double.compare(this.price,goods.price);
        }
        throw new RuntimeException("传入的数据类型不一致!");
    }
}

2 定制排序:java.util.Comparator

当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码, 或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那 么可以考虑使用 Comparator 的对象来排序,强行对多个对象进行整体排 序的比较。

重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返 回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示 o1小于o2。

可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort), 从而允许在排序顺序上实现精确控制。

还可以使用 Comparator 来控制某些数据结构(如有序 set或有序映射)的 顺序,或者为那些没有自然顺序的对象 collection 提供排序。

    @Test
    public void test1(){
        Goods[] all = new Goods[4];
        all[0] = new Goods("War and Peace", 100);
        all[1] = new Goods("Childhood", 80);
        all[2] = new Goods("Scarlet and Black", 140);
        all[3] = new Goods("Notre Dame de Paris", 120);
        Arrays.sort(all,new Comparator(){
            @Override
            public int compare(Object o1, Object o2) {
                Goods goods1 = (Goods) o1;
                Goods goods2 = (Goods) o2;
                return goods1.getName().compareTo(goods2.getName());
            }
        });
        System.out.println(Arrays.toString(all));
    }

System类

package com.jerry.java;
import sun.plugin2.os.windows.Windows;
/**
 * @author jerry_jy
 * @create 2022-10-04 10:20
 */
public class SystemTest {
    public static void main(String[] args) {
        String javaVersion = System.getProperty("java.version");
        System.out.println("java的version:" + javaVersion);//java的version:1.8.0_301
        String javaHome = System.getProperty("java.home");//java的home:E:\Java_tools\jdk1.8.0_301\jre
        System.out.println("java的home:" + javaHome);
        String osName = System.getProperty("os.name");
        System.out.println("os的name:" + osName);//os的name:Windows 10
        String osVersion = System.getProperty("os.version");
        System.out.println("os的version:" + osVersion);//os的version:10.0
        String userName = System.getProperty("user.name");
        System.out.println("user的name:" + userName);//user的name:Admin
        String userHome = System.getProperty("user.home");
        System.out.println("user的home:" + userHome);//user的home:C:\Users\15718
        String userDir = System.getProperty("user.dir");
        System.out.println("user的dir:" + userDir);//user的dir:E:\CodeLife\IdeaProject\JVM
    }
}

枚举类与注解

枚举类的属性

  • 枚举类对象的属性不应允许被改动, 所以应该使用 private final 修饰
  • 枚举类的使用 private final 修饰的属性应该在构造器中为其赋值
  • 若枚举类显式的定义了带参数的构造器, 则在列出枚举值时也必须对应的 传入参数

自定义枚举类代码演示:

package com.jerry.java;
/**
 * @author jerry_jy
 * @create 2022-10-05 9:11
 */
public class SeasonTest {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        System.out.println(spring);
    }
}
//自定义枚举类
class Season {
    //1.声明Season对象的属性:private final修饰
    private final String seasonName;
    private final String seasonDesc;
    //2.私有化类的构造器,并给对象属性赋值
    private Season(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }
    //3.提供当前枚举类的多个对象:public static final的
    public static final Season SPRING = new Season("春天", "春暖花开");
    public static final Season SUMMER = new Season("夏天", "夏日炎炎");
    public static final Season AUTUMN = new Season("秋天", "秋高气爽");
    public static final Season WINTER = new Season("冬天", "冰天雪地");
    //4.其他诉求1:获取枚举类对象的属性
    public String getSeasonName() {
        return seasonName;
    }
    public String getSeasonDesc() {
        return seasonDesc;
    }
    //4.其他诉求1:提供toString()
    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

使用enum定义枚举类

使用enum定义枚举类

使用 enum 定义的枚举类默认继承了 java.lang.Enum类,因此不能再 继承其他类

枚举类的构造器只能使用 private 权限修饰符

枚举类的所有实例必须在枚举类中显式列出(, 分隔 ; 结尾)。列出的 实例系统会自动添加 public static final 修饰

必须在枚举类的第一行声明枚举类对象

package com.jerry.java;
/**
 * @author jerry_jy
 * @create 2022-10-05 9:25
 */
public enum SeasonEnum {
    SPRING("春天", "春风又绿江南岸"),
    SUMMER("夏天", "映日荷花别样红"),
    AUTUMN("秋天", "秋水共长天一色"),
    WINTER("冬天", "窗含西岭千秋雪");
    private final String seasonName;
    private final String seasonDesc;
    private SeasonEnum(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }
    public String getSeasonName() {
        return seasonName;
    }
    public String getSeasonDesc() {
        return seasonDesc;
    }
}

Enum类的主要方法:

  • values()方法:返回枚举类型的对象数组。该方法可以很方便地遍历所有的 枚举值。
  • valueOf(String str):可以把一个字符串转为对应的枚举类对象。要求字符 串必须是枚举类对象的“名字”。如不是,会有运行时异常: IllegalArgumentException。
  • toString():返回当前枚举类对象常量的名称

代码演示:

package com.jerry.java;
/**
 * @author jerry_jy
 * @create 2022-10-05 9:31
 */
public class SeasonTest1 {
    public static void main(String[] args) {
        Season1 summer = Season1.SUMMER;
        System.out.println(summer.toString());//Season1{seasonName='夏天', seasonDesc='夏日炎炎'}
        System.out.println(Season1.AUTUMN.getSeasonName());//秋天
        System.out.println(Season1.WINTER.getSeasonDesc());//冰天雪地
        System.out.println(Season1.class.getSuperclass());//class java.lang.Enum
        System.out.println("****************");
        //values():返回所有的枚举类对象构成的数组
        Season1[] values = Season1.values();
        for (int i = 0; i < values.length; i++) {
            System.out.println(values[i]);
            values[i].show();
        }
        System.out.println("****************");
        Thread.State[] values1 = Thread.State.values();
        for (int i = 0; i < values1.length; i++) {
            System.out.println(values1[i]);
        }
        //valueOf(String objName):返回枚举类中对象名是objName的对象。
        Season1 spring = Season1.valueOf("SPRING");
        spring.show();//春天在哪里?
        System.out.println(spring);//Season1{seasonName='春天', seasonDesc='春暖花开'}
        System.out.println(Season1.valueOf("WINTER1"));//Exception in thread "main" java.lang.IllegalArgumentException: No enum constant com.jerry.java.Season1.WINTER1
    }
}
interface info {
    void show();
}
enum Season1 implements info {
    SPRING("春天", "春暖花开") {
        @Override
        public void show() {
            System.out.println("春天在哪里?");
        }
    }, SUMMER("夏天", "夏日炎炎") {
        @Override
        public void show() {
            System.out.println("宁夏");
        }
    }, AUTUMN("秋天", "秋高气爽") {
        @Override
        public void show() {
            System.out.println("秋天不回来");
        }
    }, WINTER("冬天", "冰天雪地") {
        @Override
        public void show() {
            System.out.println("大约在冬季");
        }
    };
    private final String seasonName;
    private final String seasonDesc;
    private Season1(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }
    public String getSeasonName() {
        return seasonName;
    }
    public String getSeasonDesc() {
        return seasonDesc;
    }
    @Override
    public String toString() {
        return "Season1{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

注解(Annotation)

在编译时进行格式检查(JDK内置的三个基本注解)

@Override: 限定重写父类方法, 该注解只能用于方法

@Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择

@SuppressWarnings: 抑制编译器警告

package com.jerry.exer;
/**
 * @author jerry_jy
 * @create 2022-10-05 11:15
 */
public class Exer6 {
    /*
    定义一个Student类,要求重写toString()的方法,并且此方法要使用Annotation的三个基本的注释,创建Test类,输出Student类的toString方法的所有注释
     */
    public static void main(String[] args) {
        Student jerry = new Student(123, "jerry");
        System.out.println(jerry.toString());
        jerry.print();
    }
}
class Student {
    int StuID;
    String name;
    public Student(int stuID, String name) {
        StuID = stuID;
        this.name = name;
    }
    @Override
    public String toString() {
        return "重写的toString方法()";
    }
    @Deprecated
    public void print() {
        System.out.println("过时的方法");
        @SuppressWarnings("unused")
        int a = 1000;
        a=1;
        System.out.println("a= " + a);
    }
}

自定义Annotation

package com.jerry.exer;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @author jerry_jy
 * @create 2022-10-05 11:11
 */
@MyAnnotation("tom")
public class Exer5 {
    /*
    自定义annotation,里面包括1个String类型的属性,一个有默认值类型的属性,使用自定义的annotation
     */
    public static void main(String[] args) {
        System.out.println(Exer5.class.getAnnotation(MyAnnotation.class).value());//tom
    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation {
    String value() default "jerry";
}

–end–

相关文章
|
27天前
|
算法 Java 数据处理
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。
从HashSet到TreeSet,Java集合框架中的Set接口及其实现类以其“不重复性”要求,彻底改变了处理唯一性数据的方式。HashSet基于哈希表实现,提供高效的元素操作;TreeSet则通过红黑树实现元素的自然排序,适合需要有序访问的场景。本文通过示例代码详细介绍了两者的特性和应用场景。
37 6
|
15天前
|
存储 安全 Java
java.util的Collections类
Collections 类位于 java.util 包下,提供了许多有用的对象和方法,来简化java中集合的创建、处理和多线程管理。掌握此类将非常有助于提升开发效率和维护代码的简洁性,同时对于程序的稳定性和安全性有大有帮助。
37 17
|
6天前
|
安全 Java
Java多线程集合类
本文介绍了Java中线程安全的问题及解决方案。通过示例代码展示了使用`CopyOnWriteArrayList`、`CopyOnWriteArraySet`和`ConcurrentHashMap`来解决多线程环境下集合操作的线程安全问题。这些类通过不同的机制确保了线程安全,提高了并发性能。
|
11天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
50 4
|
11天前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
27 2
|
16天前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
|
20天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
20天前
|
Java API Maven
如何使用 Java 字节码工具检查类文件的完整性
本文介绍如何利用Java字节码工具来检测类文件的完整性和有效性,确保类文件未被篡改或损坏,适用于开发和维护阶段的代码质量控制。
|
19天前
|
存储 Java 编译器
java wrapper是什么类
【10月更文挑战第16天】
23 3
|
22天前
|
Java 程序员 测试技术
Java|让 JUnit4 测试类自动注入 logger 和被测 Service
本文介绍如何通过自定义 IDEA 的 JUnit4 Test Class 模板,实现生成测试类时自动注入 logger 和被测 Service。
22 5