本文概述
J2SE 5中引入了Java泛型编程, 以处理类型安全的对象。通过在编译时检测错误, 使代码稳定。
在使用泛型之前, 我们可以在集合中存储任何类型的对象, 即非泛型。现在, 泛型强制Java程序员存储特定类型的对象。
Java泛型的优势
泛型主要有3个优点。它们如下:
1)类型安全:泛型中只能容纳一种类型的对象。它不允许存储其他对象。
没有泛型, 我们可以存储任何类型的对象。
List list = new ArrayList();
list.add(10);
list.add("10");
With Generics, it is required to specify the type of object we need to store.
List<Integer> list = new ArrayList<Integer>();
list.add(10);
list.add("10");// compile-time error
2)不需要强制类型转换:无需强制转换对象。
在泛型之前, 我们需要键入强制类型转换。
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);//typecasting
After Generics, we don't need to typecast the object.
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);
3)编译时检查:在编译时进行检查, 因此在运行时不会出现问题。好的编程策略表明, 在编译时处理问题比运行时要好得多。
List<String> list = new ArrayList<String>();
list.add("hello");
list.add(32);//Compile Time Error
使用通用集合的语法
ClassOrInterface<Type>
在Java中使用泛型的示例
ArrayList<String>
Java泛型的完整示例
在这里, 我们使用ArrayList类, 但是你可以使用任何集合类, 例如ArrayList, LinkedList, HashSet, TreeSet, HashMap, Comparator等。
import java.util.*;
class TestGenerics1{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();
list.add("rahul");
list.add("jai");
//list.add(32);//compile time error
String s=list.get(1);//type casting is not required
System.out.println("element is: "+s);
Iterator<String> itr=list.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
import java.util.*;
class TestGenerics1{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();
list.add("rahul");
list.add("jai");
//list.add(32);//compile time error
String s=list.get(1);//type casting is not required
System.out.println("element is: "+s);
Iterator<String> itr=list.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}
}
立即测试
输出:
element is: jai
rahul
jai
使用Map的Java泛型示例
现在, 我们将使用泛型使用map元素。在这里, 我们需要传递键和值。让我们通过一个简单的例子来理解它:
import java.util.*;
class TestGenerics2{
public static void main(String args[]){
Map<Integer, String> map=new HashMap<Integer, String>();
map.put(1, "vijay");
map.put(4, "umesh");
map.put(2, "ankit");
//Now use Map.Entry for Set and Iterator
Set<Map.Entry<Integer, String>> set=map.entrySet();
Iterator<Map.Entry<Integer, String>> itr=set.iterator();
while(itr.hasNext()){
Map.Entry e=itr.next();//no need to typecast
System.out.println(e.getKey()+" "+e.getValue());
}
}}
立即测试
输出量
1 vijay
2 ankit
4 umesh
通用类
可以引用任何类型的类称为泛型类。在这里, 我们使用T类型参数创建特定类型的泛型类。
让我们看一个简单的示例来创建和使用泛型类。
创建一个通用类:
class MyGen<T>{
T obj;
void add(T obj){this.obj=obj;}
T get(){return obj;}
}
T类型表示它可以引用任何类型(例如String, Integer和Employee)。你为该类指定的类型将用于存储和检索数据。
使用通用类:
让我们看一下使用通用类的代码。
class TestGenerics3{
public static void main(String args[]){
MyGen<Integer> m=new MyGen<Integer>();
m.add(2);
//m.add("vivek");//Compile time error
System.out.println(m.get());
}}
立即测试
输出量
2
类型参数
类型参数命名约定对于彻底学习泛型很重要。常见的类型参数如下:
- T型
- 电子元素
- K键
- N-号码
- V-值
通用方法
像通用类一样, 我们可以创建一个通用方法, 该方法可以接受任何类型的参数。在这里, 参数的范围限于声明它的方法。它允许静态和非静态方法。
我们来看一个简单的java通用方法来打印数组元素的示例。我们在这里用E表示元素。
public class TestGenerics4{
public static < E > void printArray(E[] elements) {
for ( E element : elements){
System.out.println(element );
}
System.out.println();
}
public static void main( String args[] ) {
Integer[] intArray = { 10, 20, 30, 40, 50 };
Character[] charArray = { 'J', 'A', 'V', 'A', 'T', 'P', 'O', 'I', 'N', 'T' };
System.out.println( "Printing Integer Array" );
printArray( intArray );
System.out.println( "Printing Character Array" );
printArray( charArray );
}
}
立即测试
输出量
Printing Integer Array
10
20
30
40
50
Printing Character Array
J
A
V
A
T
P
O
I
N
T
Java泛型中的通配符
? (问号)符号表示通配符元素。它表示任何类型。如果我们写<?扩展Number>, 表示Number的任何子类, 例如Integer, Float和double。现在我们可以通过任何子类对象调用Number类的方法。
我们可以使用通配符作为参数, 字段, 返回类型或局部变量的类型。但是, 不允许将通配符用作泛型方法调用, 泛型类实例创建或超类型的类型参数。
让我们通过以下示例了解它:
import java.util.*;
abstract class Shape{
abstract void draw();
}
class Rectangle extends Shape{
void draw(){System.out.println("drawing rectangle");}
}
class Circle extends Shape{
void draw(){System.out.println("drawing circle");}
}
class GenericTest{
//creating a method that accepts only child class of Shape
public static void drawShapes(List<? extends Shape> lists){
for(Shape s:lists){
s.draw();//calling method of Shape class by child class instance
}
}
public static void main(String args[]){
List<Rectangle> list1=new ArrayList<Rectangle>();
list1.add(new Rectangle());
List<Circle> list2=new ArrayList<Circle>();
list2.add(new Circle());
list2.add(new Circle());
drawShapes(list1);
drawShapes(list2);
}}
输出量
drawing rectangle
drawing circle
drawing circle
上界通配符
上限通配符的目的是减少对变量的限制。它将未知类型限制为特定类型或该类型的子类型。它通过声明通配符(“?”), 扩展名(在类的情况下)或实现(在接口的情况下)关键字以及其上限来使用。
句法
List<? extends Number>
这里,
?是通配符。
扩展, 是一个关键字。
数字, 是java.lang包中存在的类
假设我们要为Number及其子类型(如Integer, Double)的列表编写方法。使用列表<? extend Number>适用于Number类型或其任何子类的列表, 而List <Number>仅适用于Number类型的列表。那么, 列表<?扩展Number>的限制比List <Number>的限制少。
上界通配符示例
在此示例中, 我们使用上限通配符为List <Integer>和List <Double>编写方法。
import java.util.ArrayList;
public class UpperBoundWildcard {
private static Double add(ArrayList<? extends Number> num) {
double sum=0.0;
for(Number n:num)
{
sum = sum+n.doubleValue();
}
return sum;
}
public static void main(String[] args) {
ArrayList<Integer> l1=new ArrayList<Integer>();
l1.add(10);
l1.add(20);
System.out.println("displaying the sum= "+add(l1));
ArrayList<Double> l2=new ArrayList<Double>();
l2.add(30.0);
l2.add(40.0);
System.out.println("displaying the sum= "+add(l2));
}
}
立即测试
输出量
displaying the sum= 30.0
displaying the sum= 70.0
无限通配符
无限制的通配符类型表示未知类型的列表, 例如List <?>。这种方法在以下情况下很有用:-
- 通过使用Object类中提供的功能实现给定方法时。
- 当泛型类包含不依赖于type参数的方法时。
无界通配符示例
import java.util.Arrays;
import java.util.List;
public class UnboundedWildcard {
public static void display(List<?> list)
{
for(Object o:list)
{
System.out.println(o);
}
}
public static void main(String[] args) {
List<Integer> l1=Arrays.asList(1, 2, 3);
System.out.println("displaying the Integer values");
display(l1);
List<String> l2=Arrays.asList("One", "Two", "Three");
System.out.println("displaying the String values");
display(l2);
}
}
立即测试
输出量
displaying the Integer values
1
2
3
displaying the String values
One
Two
Three
下界通配符
下限通配符的目的是将未知类型限制为特定类型或该类型的超类型。通过先声明通配符(“?”), 再声明super关键字, 再声明其下限来使用它。
句法
List<? super Integer>
这里,
?是通配符。
超级, 是关键字。
整数, 是包装器类。
假设我们要为Integer列表及其超类型(如Number, Object)编写方法。使用列表<? super Integer>适用于Integer类型的列表或其任何超类, 而List <Integer>仅适用于Integer类型的列表。那么, 列表<? super Integer>的限制比List <Integer>的限制少。
下界通配符示例
在此示例中, 我们使用下限通配符为List <Integer>和List <Number>编写方法。
import java.util.Arrays;
import java.util.List;
public class LowerBoundWildcard {
public static void addNumbers(List<? super Integer> list) {
for(Object n:list)
{
System.out.println(n);
}
}
public static void main(String[] args) {
List<Integer> l1=Arrays.asList(1, 2, 3);
System.out.println("displaying the Integer values");
addNumbers(l1);
List<Number> l2=Arrays.asList(1.0, 2.0, 3.0);
System.out.println("displaying the Number values");
addNumbers(l2);
}
}
立即测试
输出量
displaying the Integer values
1
2
3
displaying the Number values
1.0
2.0
3.0
评论前必须登录!
注册