个性化阅读
专注于IT技术分析

Java泛型使用全解

本文概述

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

类型参数

类型参数命名约定对于彻底学习泛型很重要。常见的类型参数如下:

  1. T型
  2. 电子元素
  3. K键
  4. N-号码
  5. 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

赞(0)
未经允许不得转载:srcmini » Java泛型使用全解

评论 抢沙发

评论前必须登录!