什么是泛型?有什么作用?
什么是泛型?有什么作用?
QA
Step 1
Q:: 什么是泛型?有什么作用?
A:: Java 泛型(Generics)是 JDK 5
中引入的一个特性。泛型允许类、接口和方法操作于指定的数据类型,提供了编译时类型安全性。泛型的主要作用是提高代码的可重用性和类型安全性,例如使用 ArrayList<T>
,其中 T 可以是任何对象类型。使用泛型可以减少类型转换的需求,并在编译时检测类型错误,避免运行时异常。
Step 2
Q:: 如何定义一个泛型类?
A:: 定义泛型类时,可以在类名后面使用尖括号 <>
来声明泛型参数。比如:
public class Box<T> {
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
其中 T
是泛型类型参数,类中的成员变量和方法都可以使用这个类型。
Step 3
Q:: 什么是类型擦除?为什么 Java 的泛型是通过类型擦除实现的?
A:: 类型擦除是 Java 编译器在编译时处理泛型的方式。泛型信息在编译后被擦除,这意味着泛型参数会被替换为它们的边界类型或 Object 类型。这是为了与 Java 早期版本中的非泛型代码兼容。这也意味着在运行时,泛型的类型信息无法直接获取,这种实现方法简化了 JVM 的设计和实现。
Step 4
Q:: 通配符 ?
在泛型中有什么作用?
A:: 通配符 ?
在泛型中表示一个未知的类型。它通常用于泛型类或方法的参数中,允许方法适用于多种泛型类型。比如 List<?>
表示可以持有任何类型对象的列表。通配符可以限制为上边界或下边界,如 List<? extends Number>
表示持有 Number 类或其子类的列表。
Step 5
Q:: 泛型方法是什么?如何定义?
A:: 泛型方法是在方法定义中引入一个或多个类型参数。类型参数在方法名之前声明,并且可以在方法的返回类型、参数类型以及方法体内使用。例如:
public <T> void printArray(T[] inputArray) {
for (T element : inputArray) {
System.out.println(element);
}
}
这个方法可以打印任何类型的数组。
Step 6
Q:: 可以在泛型类或方法中使用基本类型吗?
A:: 不能直接在泛型中使用基本数据类型(如 int
、char
等)。如果需要使用基本类型,必须使用对应的包装类(如 Integer
、Character
等)。这是因为 Java 泛型是基于对象的,基本类型不适用于泛型。
用途
面试泛型的相关内容是为了考察候选人对 Java 语言特性的理解和应用能力。泛型在实际开发中广泛应用于集合类、框架库和泛型算法等场景。它能提高代码的重用性和类型安全性,减少运行时类型转换错误。在处理不同类型的集合、编写通用工具类或方法时,泛型尤为重要。此外,理解泛型的类型擦除机制对解决泛型相关的编译错误或设计更加高效和类型安全的 API 也很有帮助。\n相关问题
泛型的使用方式有哪几种?
QA
Step 1
Q:: 什么是泛型?
A:: 泛型是 Java 中的一种机制,允许你在定义类、接口和方法时使用类型参数。这些类型参数在实例化时会被具体的类型替代,泛型可以使代码更具通用性和可重用性,同时还能保证类型安全。
Step 2
Q:: 泛型类的定义和使用方式是什么?
A:: 泛型类是指在类的定义中使用了一个或多个类型参数的类。定义泛型类时,可以在类名后面的尖括号中定义类型参数。使用泛型类时,在实例化类的对象时,需要指定具体的类型。例如:Generic<Integer> genericInteger = new Generic<>(123456);
。
Step 3
Q:: 泛型接口如何实现?
A:: 泛型接口是指在接口定义时使用了类型参数的接口。实现泛型接口时,可以在实现类中保留泛型,或者在实现时指定具体的类型。例如:class GeneratorImpl<T> implements Generator<T>
保留泛型,或者class GeneratorImpl implements Generator<String>
指定具体类型。
Step 4
Q:: 泛型方法是什么?如何使用?
A:: 泛型方法是在方法定义中引入类型参数的一个方法。与泛型类和泛型接口不同,泛型方法的类型参数是在方法声明中定义的,可以独立于类或接口的类型参数。使用时直接在方法调用时传入参数类型,如:printArray(intArray)
,printArray(stringArray)
。
Step 5
Q:: 为什么要使用泛型?
A:: 使用泛型可以提高代码的通用性和重用性,减少代码的重复,并且在编译时提供类型检查,避免类型转换错误。泛型还可以减少对类型强制转换的需要,提升代码的可读性和安全性。
Step 6
Q:: 泛型的类型擦除是什么?
A:: Java 的泛型在编译时会进行类型擦除,即在编译之后,泛型类型会被替换为它的限定类型或 Object 类型。这意味着泛型信息在运行时是不可用的。类型擦除机制是为了与 Java 的泛型之前的版本保持兼容。
Step 7
Q:: 泛型中的通配符(Wildcard)是什么?
A:: 泛型通配符用于表示未知类型。常用的通配符有:?
表示不确定的类型,? extends T
表示 T 的子类型,? super T
表示 T 的父类型。在需要泛型类或方法可以接受多种类型但不希望指定具体类型时,可以使用通配符。
用途
面试泛型的目的是为了评估候选人对 Java 语言高级特性的掌握情况,特别是泛型的使用能够大幅度提升代码的灵活性、可重用性和类型安全性。在实际生产环境中,泛型通常用于创建集合、库函数或通用的业务逻辑类库,确保代码在处理多种类型时保持一致性和安全性。例如在设计框架时,泛型可以使得框架能够处理用户提供的不同类型的数据而无需对每种数据类型都写专门的代码。\n相关问题
项目中哪里用到了泛型?
QA
Step 1
Q:: 项目中哪里用到了泛型?
A:: 在项目中,泛型被广泛用于提高代码的复用性和类型安全性。例如:
1. 自定义接口通用返回结果 CommonResult<T>
,通过参数 T 可以根据具体的返回类型动态指定结果的数据类型,这样可以避免多次定义类似的返回结构。
2. 定义 Excel 处理类 ExcelUtil<T>
,用于动态指定 Excel 导出的数据类型,使得同一个处理类可以处理不同的数据结构。
3.
构建集合工具类(参考 Collections 中的 sort、binarySearch 方法),这些工具类使用泛型来处理不同类型的集合,提高了代码的通用性。
Step 2
Q:: 泛型的定义和作用是什么?
A:: 泛型是Java中的一种特性,允许在类、接口和方法中使用类型参数。其主要作用有:
1.
提高代码的重用性:通过泛型可以编写与类型无关的通用代码。
2.
增强类型检查:在编译期间就可以检查类型错误,减少运行时异常。
3.
避免类型转换:使用泛型可以减少显式的类型转换,提高代码的可读性和安全性。
Step 3
Q:: 如何在自定义类中使用泛型?
A:: 在自定义类中使用泛型可以通过在类名后添加类型参数来实现。例如:
public class Box<T> {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
这个 Box 类可以用于存储任意类型的对象。
用途
面试泛型的使用,主要是为了考察候选人对Java语言高级特性的掌握程度,特别是对代码复用性、类型安全性、可读性和维护性的理解。在实际生产环境中,泛型通常用于:\n`1.` 定义通用的数据结构,如列表、映射等。\n`2.` 编写与类型无关的工具类和方法,如排序、搜索等。\n`3.` 提供灵活的API,使得库和框架能够处理各种数据类型,而不失去类型检查的能力。\n掌握泛型的使用可以帮助开发者编写更健壮、可维护的代码。\n相关问题
什么是泛型擦除机制?为什么要擦除?
QA
Step 1
Q:: 什么是泛型擦除机制?为什么要擦除?
A:: Java 的泛型擦除机制是指在编译期间,所有的泛型信息都会被移除(擦除)。在 Java 编译器生成的字节码中,泛型类型被替换为其上限(如 T extends Comparable 被替换为 Comparable)或 Object。如果没有上限,泛型 T 会被擦除为 Object。这种机制的主要目的是为了确保向后兼容性,即使在引入泛型之前编写的代码也能与新版本的 Java 一起工作,同时减少虚拟机运行时的开销。
Step 2
Q:: 为什么使用泛型?直接使用 Object 不可以吗?
A:: 泛型的主要优势在于提高了代码的安全性和可读性。使用泛型可以在编译期间进行类型检查,减少运行时错误的发生。同时,使用泛型消除了手动类型转换的需要,简化了代码并降低了错误率。虽然使用 Object 可以实现类似的功能,但会引入额外的类型转换操作,增加了代码复杂性,并且可能导致类型转换异常。
Step 3
Q:: 泛型擦除会带来什么问题?如何避免这些问题?
A:: 泛型擦除可能导致类型信息丢失,使得某些操作(如方法重载)在编译时无法区分不同的泛型类型,进而导致编译错误或运行时错误。为了避免这些问题,可以使用特定的类型标记(如使用 Class<T>
作为方法参数)或者通过自定义的类型转换逻辑来处理复杂的泛型场景。
Step 4
Q:: 如何通过反射操作泛型?
A:: 由于泛型类型在运行时被擦除为 Object,可以使用反射机制绕过编译器的类型检查。通过获取泛型类的 Class 对象,然后调用 getDeclaredMethod()
方法,可以动态调用泛型方法。例如,在运行时使用反射添加一个非泛型类型到泛型集合中。然而,这种操作虽然能绕过编译检查,但会在运行时导致潜在的类型安全问题,因此在实际开发中应尽量避免使用。
Step 5
Q:: 泛型方法和泛型类的区别是什么?
A:: 泛型方法是在方法声明中引入泛型参数,使方法能够处理不同类型的参数。泛型类则是在类定义中引入泛型参数,使类的实例可以持有或操作不同类型的数据。泛型方法的类型参数仅在该方法内有效,而泛型类的类型参数在整个类中都有效。
用途
面试这个内容主要是为了考察候选人对 Java 泛型机制的理解和掌握程度。泛型是 Java 语言中重要的一部分,能帮助开发者编写类型安全且可重用的代码。在实际生产环境中,泛型广泛用于集合框架、各种工具类、接口定义等场景中,能够有效减少类型转换错误,提升代码的可靠性和维护性。理解泛型擦除及其影响有助于开发者编写更加健壮的代码,避免因类型信息丢失带来的潜在问题。\n相关问题
什么是桥方法?
QA
Step 1
Q:: 什么是桥方法?
A:: 桥方法(Bridge Method)是编译器在编译过程中自动生成的方法,用于保证泛型类在继承时能够正确地实现多态。在Java中,泛型类型在编译时会被擦除(类型擦除),如果子类中重写了父类的泛型方法,但是方法签名不同,编译器会生成一个桥方法来帮助调用正确的重写方法。桥方法是编译器生成的,开发者不需要手写。
Step 2
Q:: 泛型的限制有哪些?为什么?
A:: 泛型的限制主要是由Java的泛型擦除机制引起的。泛型在编译时会被擦除为其上限(通常为Object),这带来了如下限制:
1.
无法实例化泛型类型的对象,因为擦除后无法确定实际类型。
2.
泛型参数不能是基本类型,因为泛型擦除后只接受引用类型。
3.
不能创建泛型类型的数组,因为擦除后无法进行类型判断。
4.
泛型无法使用 instanceof
和 getClass()
进行类型判断。
5.
不能实现两个不同泛型参数的同一接口,因为擦除后可能导致桥方法冲突。
6.
泛型变量不能使用 static
修饰符,因为泛型是在实例级别定义的,而 static
属于类级别。
用途
面试中考察桥方法及泛型限制的知识,主要是为了评估候选人对Java语言机制的深入理解,特别是泛型和多态的应用。在实际生产环境中,这些知识点在编写框架、库、工具类时非常重要。了解桥方法有助于调试复杂的泛型代码,并理解编译器生成的字节码,确保代码行为符合预期。泛型的限制知识则能够帮助开发者在设计API和框架时做出合理的设计选择,避免运行时错误。\n相关问题
以下代码是否能编译,为什么?
QA
Step 1
Q:: 这段代码是否可以编译通过?为什么?
A::
public final class Algorithm {
public static <T> T max(T x, T y) {
return x > y ? x : y;
}
}
无法编译通过。因为泛型 T
在编译时会被类型擦除为 Object
,Object
类型不支持 >
操作符的比较。为了解决这个问题,可以使用 Comparable
接口来约束泛型,修改后的代码如下:
public final class Algorithm {
public static <T extends Comparable<T>> T max(T x, T y) {
return x.compareTo(y) > 0 ? x : y;
}
}
Step 2
Q:: 这段代码是否可以编译通过?为什么?
A::
public class Singleton<T> {
public static T getInstance() {
if (instance == null)
instance = new Singleton<T>();
return instance;
}
private static T instance = null;
}
无法编译通过。静态变量和方法不能引用类的类型参数 T
,因为类型参数 T
是与实例相关的,而静态上下文是与类相关的。可以考虑使用非静态方式实现单例模式,或者让 Singleton
类不依赖泛型 T
。
用途
这些面试题旨在考察候选人对 Java 泛型机制的理解。Java 中的泛型是用于增强代码的类型安全性和可读性的关键特性,但其也带来了类型擦除等复杂概念,容易导致新手在使用时犯错。理解这些概念对于编写更健壮和高效的代码至关重要。在实际生产环境中,开发者常常需要编写通用代码,避免重复和提高代码的可维护性,因此需要对泛型有深刻的理解。错误的泛型使用可能导致代码难以调试、运行时类型错误等问题,因此在设计库、框架或通用工具类时,准确理解和正确应用泛型至关重要。\n相关问题
什么是通配符?有什么作用?
QA
Step 1
Q:: 什么是通配符?有什么作用?
A:: 通配符是一种用于泛型中的特殊符号,主要用于表示一种不确定的泛型类型。它的作用是允许泛型类型参数在某些情况下具有灵活性,尤其是在需要泛型类型协变或逆变时。例如,? extends T
表示可以接收T的任意子类型,而? super T
表示可以接收T的任意父类型。通配符解决了泛型在某些场景下无法协变的问题,使得代码可以更通用、更具复用性。
Step 2
Q:: 泛型中的通配符 ? extends T
和 ? super T
有什么区别?
A:: ? extends T
限定了泛型的上界,表示可以接受 T 及其子类的类型。? super T
限定了泛型的下界,表示可以接受 T 及其父类的类型。前者常用于读取的场景,而后者则更适合写入的场景。
Step 3
Q:: 什么时候应该使用 ? extends T
和 ? super T
?
A:: ? extends T
通常在你需要读取一个泛型集合,并且不希望集合被修改时使用。因为 ? extends T
保证了元素的类型是 T 或其子类,但不能安全地向集合中添加元素。? super T
则是在你需要向集合中添加元素时使用,它保证了你可以向集合中添加 T 或 T 的子类。
Step 4
Q:: Java中的泛型如何实现类型安全?
A:: Java 的泛型通过在编译时进行类型检查来实现类型安全。泛型允许在使用时指定具体类型,编译器在编译时检查类型的正确性,防止类型转换错误。这种机制消除了在运行时进行强制类型转换的需要,减少了可能的 ClassCastException。
Step 5
Q:: 为什么 Java 中的泛型在运行时被擦除?
A:: Java 中的泛型在运行时被类型擦除(Type Erasure),这意味着泛型类型参数在编译后会被擦除,替换为其边界类型或 Object。这是为了兼容 Java 的泛型之前的版本。虽然这提供了向后兼容性,但也带来了一些限制,例如不能直接获取泛型参数的实际类型。
用途
面试中经常考察通配符和泛型的相关知识,因为在实际开发中,泛型和通配符被广泛用于定义通用接口、集合类和其他需要灵活处理不同类型数据的场景。了解和正确使用通配符有助于开发者编写更加灵活、健壮的代码,尤其是在设计框架或库时。比如,当我们需要处理不同类型的集合或接口实现时,通配符提供了极大的灵活性,允许代码与多种类型兼容而不损失类型安全性。在高性能、可扩展性和代码复用要求高的生产环境中,掌握泛型和通配符的使用是非常必要的。\n相关问题
通配符 ?和常用的泛型 T 之间有什么区别?
QA
Step 1
Q:: 通配符 ?
和泛型 T 之间的区别是什么?
A:: 通配符 ? 和泛型 T 都是 Java 中用于泛型编程的关键字,但它们的使用场景和目的有所不同。T 是一个类型参数,通常在定义泛型类、泛型接口或泛型方法时使用,用来表示某种具体类型。T 可以在方法或类中声明变量、常量、参数等。而 ? 是一个通配符,通常用于泛型的使用场景,比如在定义泛型方法的形参或在泛型类中使用特定类型时,用来表示某种不确定的类型。T 在编译时会被擦除为其限定的类型或 Object,而 ?
则用于在调用泛型方法或类时进行类型匹配。
Step 2
Q:: 什么是泛型擦除?
A:: 泛型擦除是指 Java 在编译期会移除泛型类型信息,用它们的边界类型(如果没有指定边界类型则是 Object)来替换泛型参数。例如,一个 List<T> 在编译后实际处理的是 List<Object>
,具体的类型信息在运行时是无法得知的。泛型擦除确保了向后兼容性,使得泛型代码能够与没有泛型的 Java 代码一同运行。
Step 3
Q:: 通配符 ? 和 ? extends T 以及 ?
super T 之间的区别是什么?
A:: ? 表示不确定的某种类型,可以是任何类型。? extends T 表示某种类型是 T 的子类型(包括 T 本身),适用于需要读取类型为 T 的元素但不允许修改的场景。?
super T 则表示某种类型是 T 的父类型(包括 T 本身),适用于可以插入类型为 T 的元素的场景,但读取时只能保证是 Object 类型。
Step 4
Q:: 泛型方法如何定义和使用?
A:: 泛型方法是在方法的定义中引入一个或多个类型参数,通常在返回类型之前使用 <T> 来声明。比如,public <T> T getElement(List<T> list, int index) 表示该方法接收一个 List<T>
类型的参数,并返回该列表中的某个元素。泛型方法在调用时,可以显式地指定类型,也可以依赖 Java 的类型推断来自动确定类型。
用途
面试中考察泛型的知识,主要是为了确保候选人对 Java 类型系统的理解程度,特别是泛型的安全性和灵活性。在实际的生产环境中,泛型用于编写类型安全且可重用的代码,尤其是在使用集合框架时。通过泛型,可以减少类型转换错误,增强代码的可读性和可维护性。泛型方法和通配符则提供了更加灵活的 API 设计方式,使得代码可以适应不同的类型需求。\n相关问题
什么是无界通配符?
QA
Step 1
Q:: 什么是无界通配符?
A:: 无界通配符使用 '?'
作为通配符符号,用于泛型类或泛型方法中。它可以接受任何类型的数据,常用于方法的参数中,当你不关心或不依赖具体的类型时,可以使用无界通配符来进行处理。
Step 2
Q:: List<?>
和 List 有什么区别?
A:: List<?>
表示持有某种具体类型的 List,但该类型未知,因此在向其中添加元素时会报错;而 List 表示持有的元素类型是 Object,可以添加任何类型的元素,但编译器会给出警告信息。这两个之间的主要区别在于类型安全性与编译时的类型检查。
Step 3
Q:: 为什么不能向 List<?>
中添加元素?
A:: 因为 List<?> 不允许在编译时确定元素的具体类型,因此编译器无法确保类型安全。为了避免潜在的类型转换错误,编译器禁止在 List<?>
中添加元素。唯一的例外是可以添加 null,因为它适用于任何引用类型。
Step 4
Q:: 可以在 List<?>
中读取元素吗?
A:: 可以读取元素,但由于编译器无法确定其具体类型,因此读取的元素会被视为 Object 类型。如果需要使用具体的类型,可能需要进行类型转换。
用途
面试时讨论无界通配符的原因是为了评估候选人对 Java 泛型的理解程度。泛型在 Java 中用于编写通用的、类型安全的代码,尤其是在处理集合框架时。了解无界通配符的使用场景有助于编写更加灵活和可重用的代码。生产环境中,当方法不需要依赖具体的类型参数时,通常会使用无界通配符,例如在编写通用工具类、数据结构的操作方法时。\n相关问题
什么是上边界通配符?什么是下边界通配符?
QA
Step 1
Q:: 什么是上边界通配符?
A:: 上边界通配符是指在使用泛型时,使用 <? extends 类>
语法,表示泛型类型的实参必须是指定类的子类或本身。这种通配符允许我们在泛型中传入多个子类型的对象,确保了类型的安全性。
Step 2
Q:: 什么是下边界通配符?
A:: 下边界通配符是指在使用泛型时,使用 <? super 类>
语法,表示泛型类型的实参必须是指定类的父类或本身。这种通配符允许我们在泛型中传入多个父类型的对象,用于泛型方法中进行类型限制。
Step 3
Q:: ? extends xxx
和? super xxx
有什么区别?
A:: ? extends xxx
表示类型的上限,泛型类型只能是xxx及其子类,适用于只需要读取数据的场景。而? super xxx
表示类型的下限,泛型类型只能是xxx及其父类,适用于需要写入数据的场景。
Step 4
Q:: T extends xxx
和? extends xxx
有什么区别?
A:: T extends xxx
用于定义泛型类和方法,表明T可以是xxx或其子类型。? extends xxx
用于定义方法参数,表示传入的类型可以是xxx或其子类型,主要用于泛型方法中限制参数类型。
Step 5
Q:: Class<?>
和Class
的区别?
A:: Class 是一个泛型类,直接使用 Class 会有一个类型警告,因为泛型类型被擦除后是原始类型。使用 Class<?>
可以避免类型警告,表示接收任意类型的 Class 对象。
用途
面试这些内容主要是为了考察候选人对 Java 泛型的深入理解和实际运用能力。在实际生产环境中,这些知识通常用于编写具有通用性和类型安全性的代码,例如泛型集合、泛型方法和接口等。在处理复杂的数据结构或需要对泛型类型进行灵活处理时,这些知识至关重要。理解和正确使用边界通配符可以避免潜在的 ClassCastException,提高代码的健壮性和可维护性。\n相关问题
以下代码是否能编译,为什么?
QA
Step 1
Q:: 为什么以下代码无法编译?
A::
class Shape { /* ... */ }
class Circle extends Shape { /* ... */ }
class Rectangle extends Shape { /* ... */ }
class Node<T> { /* ... */ }
Node<Circle> nc = new Node<>();
Node<Shape> ns = nc;
该代码无法编译的原因是 Node<Circle>
并不是 Node<Shape>
的子类。Java 中的泛型是不可协变的,这意味着即使 Circle
是 Shape
的子类,Node<Circle>
也不是 Node<Shape>
的子类。
Step 2
Q:: 为什么以下代码可以编译?
A::
class Shape { /* ... */ }
class Circle extends Shape { /* ... */ }
class Rectangle extends Shape { /* ... */ }
class Node<T> { /* ... */ }
class ChildNode<T> extends Node<T>{
}
ChildNode<Circle> nc = new ChildNode<>();
Node<Circle> ns = nc;
该代码可以编译,因为 ChildNode<Circle>
是 Node<Circle>
的子类,继承关系允许这种类型转换。
Step 3
Q:: 为什么以下代码可以编译?
A::
public static void print(List<? extends Number> list) {
for (Number n : list)
System.out.print(n + " ");
System.out.println();
}
该代码可以编译,List<? extends Number>
允许接收 Number
或其子类的列表作为参数,但由于泛型的擦除机制,无法向其中添加新的元素。这个方法确保了从列表中取出的元素都是 Number
类型。
Step 4
Q:: 什么是泛型擦除机制?
A:: Java 的泛型是伪泛型,在编译时,所有的泛型信息都会被擦除,这就是所谓的类型擦除。编译器会将泛型类型参数 T 擦除为 Object 或其边界类型。这种机制的目的是为了在引入泛型时不增加虚拟机的负担。
Step 5
Q:: 什么是桥方法?
A:: 桥方法是编译器自动生成的,用于继承泛型类时确保多态性。假设一个类继承了泛型类并对其中的方法进行了重载,那么在编译时,编译器会自动生成一个桥方法,以确保重载的方法能够正确地覆盖父类的版本。这是为了确保泛型擦除后,仍然能够维持多态行为。
Step 6
Q:: 泛型有哪些限制?
A:: 由于泛型的擦除机制,泛型在使用时有一些限制:
-
不能直接实例化泛型类型。
-
泛型参数不能是基本类型。
-
不能创建泛型类型的数组。
-
不能使用 instanceof
或 getClass()
进行类型判断。
-
不能实现两个相同泛型接口的不同参数类型。
-
不能用 static
修饰泛型变量。
Step 7
Q:: 如何实现泛型方法?
A:: 泛型方法可以在方法定义中声明一个或多个类型参数,用于方法的参数或返回值。例如:
public static <E> void printArray(E[] inputArray) {
for (E element : inputArray) {
System.out.printf("%s ", element);
}
System.out.println();
}