举一个常用的例子,我们在做API请求返回响应结果时,我们可以利用枚举去定义我们的响应体,根据不同的变量,返回响应的结果。来看一个我写好的例子:

public enum Response implements ResponseInter {
    SUCCESS(200, null, "success"),
    Fail(0, null, "错误"),
    Response(0, null, "");
    private String msg;
    private Integer code;
    private Object data;
    Response(int code, String data, String msg) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    public String getMsg() {
        return msg;
    public void setMsg(String msg) {
        this.msg = msg;
    public Integer getCode() {
        return code;
    public void setCode(Integer code) {
        this.code = code;
    public Object getData() {
        return data;
    public void setData(Object data) {
        this.data = data;
    @Override
    public ResponseData response(int code, String data, String msg) {
        this.code = code;
        this.msg = msg;
        this.data = data;
        return getResponse();
    private ResponseData getResponse() {
        ResponseData response = new ResponseData();
        response.setData(this.data);
        response.setCode(this.code);
        response.setMsg(this.msg);
        return response;
    public ResponseData success() {
       return getResponse();
    public ResponseData fail() {
        return getResponse();

枚举也是一种特殊的类 ,所以它也可以实现接口。 当我们定义 SUCCESS(200, null, "success")这种带括号的成员时,idea会自动提示你去创建它的构造函数,所以后边我们可以取实例化它。

@FunctionalInterface // 函数式接口
public interface ResponseInter {
    ResponseData response(int code, String data, String msg);

这里插一个小知识点,@FunctionalInterface 表示函数式接口, 成员内部只能有一个接口方法。

如何使用?

public class EnumMain {
    public static void main(String[] args) {
        Response response = Response.SUCCESS;
        String res = JSON.toJSONString(response.success());
        Log.info(res); // {"code":200,"msg":"success"}
        Response response1 = Response.Fail;
        String res1 = JSON.toJSONString(response1.fail());
        Log.info(res1); //{"code":0,"msg":"错误"}
        Response response2 = Response.Response;
        String res2 = JSON.toJSONString(response2.response(200, "这是数据", "success"));
        Log.info(res2); // {"code":200,"data":"这是数据","msg":"success"}

是不是很简单,这里我只是粗略的定义了一下,其实还可以继续深入下去,比如我们定义各种情况下请求的状态码,这样一来,就不用我们每次手动填写具体的值了。

从字面意思讲,不确定的类型。有时候我们在写代码时,传参都需要定义具体的类型,不然编译会报错,但是有些情况我们需要复用我们的代码,但是由于强类型的要求下,我们不得已去在定义这样的类,这样显得很麻烦,所以这时候泛型,就有很大的作用了。

先看最简单的一个例子体会一下:

@Data
public class ClassMain <T> {
    private T name;

泛型类 型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。 通常使用T来代表某种类型, T不是绝对的,可以是任意。

如何使用, 类名<类型>:

ClassMain<String> f = new ClassMain<>();
f.setName("haha");
Log.info(f.getName().getClass()); // class java.lang.String

泛型接口使用还是比较多的,看一个例子:

public interface InterfaceMain<T> {
    T hello(ClassMain<T> ...obj);
@Data
public class ClassMain <T> implements InterfaceMain <T> {
    private T name;
    @Override
    public T hello(ClassMain<T> ...obj) {
        return this.name;

...obj这个表示不定参数,意思是说你可以传多个同类型的参数。

泛型通配符

有时候你在使用别人写好的类时,经常看到这样的标记, 它表示一些不确定的类型:

 // 泛型通配符
// 适合一些不确定的类型
public T hello1(ClassMain<?> obj) {
    return this.name;

通过一个例子感受一下:

public class MethodMain <T> {
    private T name;
    public <T> T hello(MethodMain<T> obj) {
        return obj.getMsg(obj.name);
    public T getMsg(T name) {
        return name;
    public <T> void getMsg(T ...arg) {
        for(T args :arg) {
            Log.info("泛型可变参 --->" + args);
    // 静态方法使用泛型时,需要定义成泛型方法, 并且与定义类无关
    public static <T> void get1(T ...arg) {
        Log.info(arg.getClass().getName());
    // 泛型中的边界
    // extends 继承 String 类型
    // 还有一个是 super 反之
    public static <T extends String> void get2(T ...arg) {
        Log.info(arg.getClass().getName());

<T extends String> 这种通常叫 泛型边界, 常用来约束我们的泛型,使它严谨一些。

泛型一问一答❓

  • Java中的泛型是什么 ? 使用泛型的好处是什么?
  • 泛型防止了那种情况的发生,它提供了编译期的类型安全,确保你只能把正确类型的对象放入集合中,避免了在运行时出现ClassCastException

  • Java的泛型是如何工作的 ? 什么是类型擦除 ?
  • 泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。

  • 什么是泛型中的限定通配符和非限定通配符 ?
  • 限定通配符对类型进行了限制。有两种限定通配符,一种是<? extends T>它通过确保类型必须是T的子类来设定类型的上界,另一种是<? super T>它通过确保类型必须是T的父类来设定类型的下界。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。另一方面<?>表示了非限定通配符,因为<?>可以用任意类型来替代。

  • List<? extends T>List <? super T>之间有什么区别 ❓
  • 这两个List的声明都是限定通配符的例子,List<? extends T>可以接受任何继承自T的类型的List,而List<? super T>可以接受任何T的父类构成的List。例如List<? extends Number>可以接受List<Integer>List<Float>

  • 如何编写一个泛型方法,让它能接受泛型参数并返回泛型类型?
  • 编写泛型方法并不困难,你需要用泛型类型来替代原始类型,比如使用T, E or K,V等被广泛认可的类型占位符。 最简单的情况下,一个泛型方法可能会像这样:

    public V put(K key, V value) {
        return cache.put(key, value);
    
  • 编写一段泛型程序来实现LRU缓存?
  • LinkedHashMap可以用来实现固定大小的LRU缓存,当LRU缓存已经满了的时候,它会把最老的键值对移出缓存。LinkedHashMap提供了一个称为removeEldestEntry()的方法,该方法会被put()和putAll()调用来删除最老的键值对。

  • 你可以把List<String>传递给一个接受List<Object>参数的方法吗?
  • 因为乍看起来String是一种Object,所以List<String>应当可以用在需要 List<Object>的地方,但是事实并非如此。真这样做的话会导致编译错误。如果你再深一步考虑,你会发现Java这样做是有意义的,因为List<Object> 可以存储任何类型的对象包括String, Integer等等,而List<String>却只能用来存储String

    List<Object> objectList;
    List<String> stringList;
    objectList = stringList;  //compilation error incompatible types
    
  • Array中可以用泛型吗?
  • 前提是你要知道Array事实上并不支持泛型,因为List可以提供编译期的类型安全保证,而Array却不能。

    blog地址 获取更多内容~

    点赞

  • “当高启强遇到陈书婷”与TCP协议
  • “老默我想吃鱼了”与五层网络模型
  • ChatGPT保姆级教程,一分钟学会使用ChatGPT!
  • 私信