龙空技术网

泛型面试题库:20道经典题目,助你提升泛型理解

Java济公 151

前言:

今天咱们对“泛型的作用及使用场景c面试题”可能比较着重,我们都想要学习一些“泛型的作用及使用场景c面试题”的相关内容。那么小编也在网摘上收集了一些有关“泛型的作用及使用场景c面试题””的相关文章,希望你们能喜欢,兄弟们快快来学习一下吧!

泛型

什么是泛型?它与类型参数化有什么不同?

什么是泛型?

泛型是程序设计语言的一种特性,它允许在定义类、接口、方法时使用类型参数在真正使用时指定具体类型,所有使用该泛型参数的地方都被统一化,保证类型一致。类型参数化是将类型参数应用于已有代码的过程,例如将一个类或接口的特定类型参数化。泛型与类型参数化的不同之处在于,泛型是一种将明确类型的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型,而类型参数化是将类型参数应用于已有代码的过程。

//泛型public class Box<T> {      private T t;        public void set(T t) {          this.t = t;      }        public T get() {          return t;      }  }//类型参数化,使用具体String类型应用已有代码过程中import java.util.ArrayList;    public class Main {      public static void main(String[] args) {          // 使用类型参数化创建ArrayList对象          ArrayList<String> stringList = new ArrayList<>();            // 添加元素到ArrayList中          stringList.add("Hello");          stringList.add("World");            // 遍历ArrayList并输出元素          for (String str : stringList) {              System.out.println(str);          }      }  }

泛型的主要用途是什么?

泛型用途

提高类型安全:泛型提供了编译时类型检查,可以在早期发现并避免类型错误,提高了程序的健壮性和可维护性。提高代码可复用性:通过将类型参数化,泛型可以使类、接口或方法适用于多种数据类型,提高了代码的复用性。增加程序灵活性:泛型使得程序可以适应不同数据类型的操作,增加了程序的灵活性和可扩展性。

泛型通配符是什么?它有哪些用途?

泛型通配符

泛型通配符是一种表示未知类型的语法,可以用于解决泛型无法协变的问题。通配符允许在使用泛型时更加灵活,它可以是问号(?)表示任意类型,也可以是问号后跟上限(? extends上限)或下限(? super下限)表示某个类型的范围。

泛型通配符的用途包括:

泛型容器类:通配符使得可以使用同一个容器类来存储不同类型的对象,例如List<?>可以存储任何类型的对象。动态类型操作:在某些情况下,需要在运行时根据实际情况处理不同类型的对象,而通配符可以帮助实现这种动态类型操作。例如,可以使用通配符来调用一个方法,该方法可以接受不同类型的参数,并在运行时确定具体的类型。类型转换:通配符可以帮助进行类型转换,尤其需要将一个类型的对象转换为另一个类型的对象时。例如,可以使用通配符来将一个父类对象转换为子类对象。

import java.util.ArrayList;  import java.util.List;    public class Main {      public static void main(String[] args) {          // 使用泛型通配符创建容器类          List<?> list = new ArrayList<>();            // 动态类型操作:根据实际需求添加不同类型的对象          list.add("Hello"); // 添加字符串类型          list.add(123); // 添加整数类型          list.add(new Object()); // 添加Object类型            // 动态类型操作:根据实际需求调用方法          processElements(list);      }        // 使用泛型通配符的方法,接受任意类型的参数并在运行时确定具体类型      public static void processElements(List<?> elements) {          for (Object obj : elements) {              if (obj instanceof String) {                  System.out.println("字符串:" + obj);              } else if (obj instanceof Integer) {                  System.out.println("整数:" + obj);              } else if (obj instanceof Object) {                  System.out.println("Object:" + obj);              }          }      }  }

什么是泛型限定?它可以解决什么问题?

泛型限定

泛型限定是对泛型类型参数的约束,它通过在泛型类型参数前添加限定符来限制泛型的使用范围。泛型限定可以解决以下问题:

类型安全问题:在使用泛型时,需要对泛型的类型做一定的限制,以保证类型安全。例如,当需要将一个字符串赋值给一个对象类型的变量时,需要确保该变量只能存储特定类型的对象,以避免运行时错误。

代码可读性问题:需要对泛型的类型参数进行限制,以使代码更加可读和易于理解。例如,当我们需要定义一个只能存储整数的泛型容器时,可以使用泛型限定来限制泛型的类型参数为Integer或其子类。

代码复用性问题:需要对不同的泛型类型参数进行不同的处理,以实现代码的复用。例如,当需要定义一个方法,该方法可以接受不同类型的参数,并在运行时确定具体的类型时,可以使用泛型限定来限制泛型的类型参数范围。

import java.util.ArrayList;  import java.util.List;    public class Main {      public static void main(String[] args) {          // 创建一个只能存储整数的泛型容器          List<Integer> intList = new ArrayList<>();          intList.add(1);          intList.add(2);          intList.add(3);            // 输出整数列表中的元素          for (Integer num : intList) {              System.out.println(num);          }      }  }

什么是原始类型和参数化类型?它们之间有何不同?

原始类型和参数化类型是Java泛型中的两种类型。原始类型是在没有使用泛型参数之前的类型,例如List、Set等。参数化类型则是使用了泛型参数的类型,例如List<String>、Set<Integer>等。

原始类型和参数化类型的主要区别在于编译时的类型安全检查和运行时的类型信息。

原始类型在编译时不进行类型安全检查,因此无法保证类型的正确性。在运行时,如果出现了类型不匹配的情况,将会抛出ClassCastException异常。

参数化类型在编译时进行类型安全检查,这有助于在编译时捕获许多类型相关的错误。在运行时,由于类型已经被参数化,因此不会出现类型不匹配的情况。

// 原始类型  List list1 = new ArrayList();  list1.add("hello");  list1.add(123); // 允许不同类型的元素添加到同一个集合中    // 参数化类型  List<String> list2 = new ArrayList<>();  list2.add("hello"); // 允许添加String类型的元素  list2.add(123); // 编译时错误,不允许添加Integer类型的元素

泛型有哪些约束?它们的作用是什么?

约束案例

泛型的约束主要有以下几种:

引用类型约束:T必须是一个引用类型,即T必须是一个类或者接口。是泛型约束中最基本的约束,它保证了泛型参数的类型安全。

值类型约束:T必须是值类型,即T必须是结构体(struct)或者基本数据类型(如int、char等)。这个约束主要用于限制泛型参数的类型范围,以确保泛型代码的安全性和正确性。

构造函数类型约束:T必须有一个公共的无参构造函数。这个约束主要用于在创建泛型实例时,确保能够正确地初始化泛型对象。

转换类型约束:T必须是一个指定的类型,如T必须是实现了某个接口的类型,或者T必须是某个类的子类。这个约束主要用于限制泛型参数的类型转换范围,以确保泛型代码的安全性和正确性。

约束的作用主要:

是限制泛型参数的类型范围,以确保泛型代码的安全性和正确性。通过限制泛型参数的类型范围,可以避免类型不匹配的问题,减少运行时错误的发生,提高代码的可维护性和可读性。同时,这些约束也可以帮助开发人员更好地理解和使用泛型,提高开发效率和代码质量。

泛型类型参数的默认值是什么?可以为其指定默认值吗?

在Java中,泛型类型参数没有默认值。泛型参数是类型参数化的基础,需要在实例化类或方法时明确指定具体的类型参数,而不是一个默认值。

例如,对于一个泛型类List<T>,你不能期望T有一个默认值,因为T可以是任何类型,包括自定义类型。同样,对于一个泛型方法,例如public <T> void printList(List<T> list),也不能期望T有一个默认值。不能为泛型类型参数指定默认值。在实例化泛型类或调用泛型方法时,必须明确指定泛型参数的类型。

什么是泛型方法?它可以解决什么问题?

泛型方法是一种在方法中使用泛型的技术。通过泛型方法,我们可以在方法中使用一个或多个类型参数,从而使方法能够适用于多种不同类型的数据。

泛型方法可以解决以下问题:

类型安全问题:泛型方法可以避免在运行时出现类型转换异常,提高代码的安全性和稳定性。

代码复用问题:通过使用泛型,我们可以编写一次代码并在不同类型的数据上重复使用,避免了为不同类型的数据编写相似但不同的代码,提高了代码的复用性。

类型参数化:泛型方法允许我们使用类型参数,使得代码更加灵活和可维护。我们可以使用通配符来处理多种不同的类型,使代码更加简洁明了。

import java.util.*;    public class GenericMethodExample {      // 泛型方法,接受两个泛型参数T和U,返回一个Map<T, U>类型的集合      public static <T, U> Set<Map.Entry<T, U>> entries(Map<T, U> map) {          return map.entrySet();      }        public static void main(String[] args) {          // 创建一个Map<String, Integer>类型的集合          Map<String, Integer> map = new HashMap<>();          map.put("one", 1);          map.put("two", 2);          map.put("three", 3);            // 使用泛型方法获取Map中的键值对集合          Set<Map.Entry<String, Integer>> entrySet = entries(map);          for (Map.Entry<String, Integer> entry : entrySet) {              System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());          }      }  }

泛型与继承有什么关系?

泛型和继承都是提高代码复用性和灵活性的重要手段。虽然它们在某些方面有相似之处,但它们的目标和机制是不同的。泛型更侧重于类型的处理,允许在编译时指定类型;而继承更侧重于类之间的关系,允许子类继承父类的属性和方法。在实际编程中,可以根据具体情况选择使用泛型或继承,或者将它们结合起来使用,以实现更好的代码组织和设计。

泛型是一种在编译时进行类型检查的编程技术,它允许程序员在定义类、接口或方法时使用类型参数。这些类型参数在实例化对象或调用方法时被具体的类型替换。泛型的主要目的是提高代码的复用性和灵活性,同时减少类型转换的错误。

继承是面向对象编程中的一个概念,它允许一个类继承另一个类的属性和方法。通过继承,子类可以复用父类的代码,并且可以扩展或覆盖父类的行为。继承是一种实现代码重用和多态性的手段。

探讨泛型和继承之间的关系。

代码复用性:继承和泛型都可以提高代码的复用性。通过继承,子类可以复用父类的代码;而通过泛型,类或方法可以在不同的类型上重复使用。

灵活性:泛型和继承都增加了代码的灵活性。通过泛型,类或方法可以处理多种不同的类型;而通过继承,子类可以根据需要扩展或修改父类的行为。

多态性:多态性是面向对象编程的一个重要概念,它允许不同的对象对同一消息做出不同的响应。在泛型和继承的情况下,它们都可以支持多态性。泛型提供了编译时多态性,而继承提供了运行时多态性。

类型的处理:在泛型的情况下,类型参数在使用之前必须明确指定;而在继承的情况下,子类会自动继承父类的类型。

什么是泛型类型擦除?它为什么在Java泛型中是必要的?

类型擦除

类型擦除是计算机程序设计时,在编译期明确去掉所编程序的类型系统。操作语义不需要程序伴随着类型,这称作“类型擦除语义”(type-erasure semantics)。在Java中,泛型是在JDK 5之后引入的,而Java本身并没有参数化类型系统。为了解决这个问题,Java采用了类型擦除的方式,将泛型信息在编译后从字节码中移除,从而保持了与旧版本Java的兼容性。擦除还能确保在编译期间和运行时保持相同的行为。这意味着无论何时定义一个泛型类型,都会自动提供一个相应的原始类型(即去掉类型参数后的泛型类型名)。类型变量会被擦除(erased),并替换为其限定类型(或者,对于无限定的变量则替换为Object)。

类型擦除在Java泛型中的必要性主要基于以下原因:

1、兼容老版本的Java编译器和虚拟机。因为泛型的实现需要改变Java的类文件格式,而类型擦除可以将所有的类型转换为Object类型,从而允许Java编译器在编译期间检查类型安全,而不会在运行时出现类型错误的问题。

2、保证在编译期间和运行时保持相同的行为。

泛型中的类型推断是什么?它是如何工作的?

泛型中的类型推断是一种自动确定泛型类型参数的过程,它基于方法调用时的参数类型和返回类型进行推断。类型推断在编译时自动进行,不需要在代码中显式指定类型参数。

类型推断的工作原理基于以下规则:

方法调用参数类型:编译器首先查看方法调用的参数类型。这些参数类型用于推断出泛型类型参数的可能范围。例如,如果一个方法被调用时传递了一个String类型的参数,那么编译器就会将String作为泛型类型参数的一个可能选项。

方法返回类型:除了参数类型之外,编译器还会考虑方法的返回类型。返回类型可以进一步限制泛型类型参数的可能范围。例如,如果一个方法的返回类型是List<String>,那么编译器就会将泛型类型参数限制为String或其子类。

上下文信息:除了方法调用的参数和返回类型之外,编译器还会考虑其他上下文信息,例如方法的签名、变量声明等。这些信息可以帮助编译器更准确地推断出泛型类型参数。

推断过程:编译器根据上述规则推断出可能的泛型类型参数,并选择最具体的类型作为实际使用的泛型类型参数。这个过程是基于Java的类型系统进行的,确保了类型安全。

什么是泛型边界?它可以解决什么问题?

泛型边界是泛型的一个重要概念,可以限制泛型变量的类型范围。它可以解决以下问题:

类型安全:泛型边界可以确保在编译时进行类型检查,避免类型转换错误。通过限制泛型变量的类型范围,可以确保在编译时检查类型是否符合要求,从而避免运行时的类型错误。

代码复用:泛型边界可以限制泛型变量的类型范围,使得代码更加通用和复用。通过定义泛型边界,可以编写适用于多种类型的代码,提高代码的复用性。

容器类型的约束:容器是编程中的重要数据结构之一,泛型边界可以对容器内的元素类型进行约束,使得容器只能存储特定类型的元素。这样可以保证容器中元素类型的正确性和一致性,减少错误和降低维护成本。

泛型与反射有什么关系?它们如何相互作用?

反射是Java中一种动态技术,可以在运行时检查类、接口、字段和方法等的信息。反射使得程序可以在运行时根据指定的类名创建对象、调用方法或访问字段,而不需要在编译时知道这些信息。

泛型是Java中一种静态类型化的技术,它允许在编译时定义类型参数化的类、接口或方法。泛型的主要目的是提高代码的复用性和类型安全,避免在运行时进行类型转换。

泛型和反射的关系主要体现在以下几个方面:

反射可以用于操作泛型类型:由于反射可以在运行时获取类的信息,因此可以用来操作泛型类型。例如,可以使用反射来获取泛型类的类型参数,或者创建泛型类型的实例。

泛型可以提供更好的类型安全:泛型在编译时进行类型检查,可以减少运行时的类型错误。这可以减少反射的使用,因为可以在编译时捕获更多的类型错误。

反射和泛型可以结合使用:在一些情况下,可能需要将反射和泛型结合使用。可以使用反射来动态地创建泛型类型的实例,或者使用反射来操作泛型类型的字段和方法。

Class<?> clazz = ...; // 获取泛型类的Class对象  Type type = clazz.getGenericSuperclass(); // 获取泛型类的实际类型参数  if (type instanceof ParameterizedType) {      ParameterizedType pType = (ParameterizedType) type;      Type[] actualTypeArguments = pType.getActualTypeArguments(); // 获取泛型参数的实际类型      // 在这里可以对实际类型参数进行操作  }Class<?> clazz = ...; // 获取泛型类的Class对象  Type type = clazz.getGenericSuperclass(); // 获取泛型类的实际类型参数  if (type instanceof ParameterizedType) {      ParameterizedType pType = (ParameterizedType) type;      Type[] actualTypeArguments = pType.getActualTypeArguments(); // 获取泛型参数的实际类型      // 在这里可以创建泛型实例,并指定实际类型参数  }

什么是泛型嵌套类型?它可以解决什么问题?

泛型嵌套类型是指在一个泛型类型内部嵌套了另一个泛型类型。这种嵌套关系可以是一层或多层。泛型嵌套类型在Java中可以通过内部类、匿名内部类等方式实现。

泛型嵌套类型可以解决以下问题:

提高代码复用性:通过将一个泛型类型嵌套在另一个泛型类型中,可以创建更加通用和复用的代码。外部泛型类型可以提供额外的类型参数,而内部泛型类型可以利用这些参数来定义自己的类型参数,从而使得内部类型更加具体和特定。这种模式可以避免重复的代码,并提高代码的维护性。

增加类型安全性:泛型嵌套类型可以提供额外的类型检查,以增加代码的类型安全性。内部泛型类型的类型参数可以从外部类型参数中继承,从而限制了内部类型的具体类型,避免了不正确的类型使用。这种约束可以在编译时捕获潜在的类型错误,提高代码的可靠性。

简化代码结构:通过将相关泛型逻辑组织在一个嵌套的泛型类型中,可以使代码结构更加清晰和易于维护。外部类型可以专注于外部逻辑,而内部类型可以专注于内部逻辑,从而降低了代码的复杂性。这种结构也有助于提高代码的可读性和可维护性。

需要注意的是,泛型嵌套类型的使用应当谨慎,避免过度使用导致代码过于复杂和难以理解。在使用时,应当根据实际需求进行设计和选择,确保代码的清晰、可读性和可维护性。

泛型与多态性有什么关系?它们如何相互作用?

多态性是面向对象程序设计中的一个基本特征,它允许一个接口被多个不同的类实现或一个类继承多个接口。多态性意味着一个对象可以有多种形态,可以在特定的情况下表现出不同的状态和行为。

泛型则是一种在编译时进行类型参数化的机制,它使得类、接口或方法可以应用于多种数据类型。通过使用泛型,可以编写更加通用和复用的代码,避免了大量的类型转换操作。

泛型和多态性的关系主要体现在以下几个方面:

泛型可以提供更好的类型安全:泛型在编译时进行类型检查,可以减少运行时的类型错误。这可以减少多态性的使用,因为可以在编译时捕获更多的类型错误。

多态性可以扩展泛型的适用范围:通过实现多态性,泛型可以被用于实现各种不同的数据类型,而不仅仅是基本类型或自定义类。多态性使得泛型类或泛型方法对于不同类型的对象实现相同的操作逻辑,从而实现更加灵活和复用的代码。

泛型和多态性可以相互补充:在某些情况下,泛型和多态性可以相互补充,以实现更加复杂的功能。例如,可以使用泛型来定义一个通用的算法,然后通过多态性来使用不同的实现方式。这样可以在保持代码通用性的同时,提高代码的灵活性和可扩展性。

泛型在集合框架中有哪些应用场景?

泛型在集合框架中的应用场景非常广泛,可以帮助你编写更加安全、清晰和复用的代码。

自定义数据结构的创建:通过泛型,你可以创建自己的数据结构,例如ArrayList、LinkedList等,并指定它们可以存储的数据类型。例如,你可以创建一个只存储整数的ArrayList,或者只存储字符串的HashMap。

集合类:Java集合框架中的许多类,如ArrayList、LinkedList、HashMap等,都使用了泛型。通过泛型,你可以更方便地使用这些集合类,并且类型更加安全,可以避免在运行时出现ClassCastException。

算法操作:通过泛型,你可以编写适用于不同数据类型的算法。例如,你可以编写一个交换两个数的算法,而不仅仅是针对整数。

接口定义:可以使用泛型来定义接口,并在实现这些接口的类中指定具体的数据类型。例如,你可以定义一个接口,该接口有一个方法用于获取列表中的元素,然后在使用该接口的类中指定列表元素的类型。

方法参数和返回值:在方法中,你可以使用泛型来指定参数和返回值的类型。这样可以使代码更加清晰和易于理解,同时也可以提高代码的复用性。

在设计模式中,泛型有哪些应用场景?

工厂模式:泛型可以用于创建可重用的工厂类,用于创建不同类型对象的实例。通过泛型,工厂类可以在编译时获取参数类型,并据此创建正确的对象实例。

public interface Shape {      void draw();  }    public class Circle implements Shape {      @Override      public void draw() {          System.out.println("Drawing Circle...");      }  }    public class Rectangle implements Shape {      @Override      public void draw() {          System.out.println("Drawing Rectangle...");      }  }    public class ShapeFactory<T extends Shape> {      public T createShape(String shapeType) {          if ("C".equalsIgnoreCase(shapeType)) {              return new Circle();          } else if ("R".equalsIgnoreCase(shapeType)) {              return new Rectangle();          } else {              throw new IllegalArgumentException("Invalid shape type");          }      }  }

模板方法模式:模板方法模式是一种行为型设计模式,它定义了一个操作中的算法骨架,将某些步骤延迟到子类中实现。在模板方法模式中,泛型可以用于定义抽象类和方法,以接受或返回不同类型的参数,从而增加代码的复用性。

public abstract class AbstractClass<T> {      protected abstract void operation(T t);      public void templateMethod() {          System.out.println("Template method called");          operation(getTypedObject()); // pass type object to template method      }      protected abstract T getTypedObject();  }    public class ConcreteClass extends AbstractClass<Integer> {      @Override      protected void operation(Integer t) {          System.out.println("Operation on Integer: " + t);      }      @Override      protected Integer getTypedObject() {          return 10; // return Integer object to template method call in AbstractClass.templateMethod()      }  }

观察者模式:观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。在观察者模式中,可以使用泛型来定义观察者和被观察者的类型,以增加代码的灵活性和复用性。

import java.util.*;    // 抽象主题类  public abstract class Subject<T> {      private List<Observer<T>> observers = new ArrayList<>();            // 添加观察者      public void addObserver(Observer<T> observer) {          observers.add(observer);      }            // 删除观察者      public void deleteObserver(Observer<T> observer) {          observers.remove(observer);      }            // 通知所有观察者更新      public void notifyObservers(T data) {          for (Observer<T> observer : observers) {              observer.update(data);          }      }  }    // 具体主题类(天气预报)  public class WeatherSubject extends Subject<String> {      private String weather;            public WeatherSubject(String weather) {          this.weather = weather;      }            public String getWeather() {          return weather;      }            public void setWeather(String weather) {          this.weather = weather;          notifyObservers(weather); // 天气变化,通知观察者更新数据      }  }    // 抽象观察者接口  public interface Observer<T> {      void update(T data);  }    // 具体观察者类(天气预报员)  public class WeatherObserver implements Observer<String> {      private String name;            public WeatherObserver(String name) {          this.name = name;      }            @Override      public void update(String data) {          System.out.println(name + " received update: " + data);      }  }

适配器模式:适配器模式是一种结构型设计模式,它通过将一个类的接口转换成客户端所期望的另一个接口形式,来解决不兼容的问题。在适配器模式中,可以使用泛型来定义适配器和被适配者的类型,以增加代码的复用性和灵活性。

import java.util.*;    // 目标接口  public interface Target<T> {      void request(T param);  }    // 源类  public class Adaptee {      public void specificRequest(String param) {          System.out.println("Adaptee: " + param);      }  }    // 适配器类  public class Adapter<T> implements Target<T> {      private Adaptee adaptee;            public Adapter(Adaptee adaptee) {          this.adaptee = adaptee;      }            @Override      public void request(T param) {          adaptee.specificRequest((String) param); // 适配器将泛型参数转换为字符串类型,传递给源类的方法      }  }public class Client {      public static void main(String[] args) {          Adaptee adaptee = new Adaptee();          Target<String> target = new Adapter<>(adaptee); // 创建适配器对象,将源对象传入适配器构造函数中          target.request("Hello, Adapter!"); // 调用目标接口方法,适配器将参数转换为字符串类型,并调用源类的方法      }  }

策略模式:策略模式是一种行为型设计模式,它定义了一系列的算法,并将每一个算法封装起来,使它们可以互相替换。在策略模式中,可以使用泛型来定义不同的策略类型,以增加代码的复用性和灵活性。

import java.util.*;    // 策略接口  public interface Strategy<T> {      void execute(T param);  }    // 具体策略类1  public class ConcreteStrategyA implements Strategy<String> {      @Override      public void execute(String param) {          System.out.println("ConcreteStrategyA: " + param);      }  }    // 具体策略类2  public class ConcreteStrategyB implements Strategy<Integer> {      @Override      public void execute(Integer param) {          System.out.println("ConcreteStrategyB: " + param);      }  }    // 上下文类,使用泛型参数  public class Context<T> {      private Strategy<T> strategy;            public Context(Strategy<T> strategy) {          this.strategy = strategy;      }            public void setStrategy(Strategy<T> strategy) {          this.strategy = strategy;      }            public void executeStrategy(T param) {          strategy.execute(param);      }  }public class Client {      public static void main(String[] args) {          Context<String> context = new Context<>(new ConcreteStrategyA()); // 创建上下文对象,传入具体策略对象A          context.executeStrategy("Hello, Strategy!"); // 执行策略方法,输出"ConcreteStrategyA: Hello, Strategy!"          context.setStrategy(new ConcreteStrategyB()); // 更换为具体策略对象B          context.executeStrategy(10); // 执行策略方法,输出"ConcreteStrategyB: 10"      }  }

标签: #泛型的作用及使用场景c面试题