package generic;
import java.util.*;
/*
* 泛型示例: 以ArrayList为例
* 泛型: 用于解决安全问题, 避免了强制转换的麻烦
*/
public class GenericDemo {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>();
al.add("abc_1");
al.add("abc_2");
al.add("abc_3");
Iterator<String> it = al.iterator();
while(it.hasNext()) {
// String s = (String)it.next();
String s = it.next();
System.out.println(s);
}
}
}
什么时候定义泛型类?
当类中要操作的引用数据类型不确定的时候,可以使用泛型类来完成。
泛型类上定义的泛型T,可以被类内的各个部分使用。
示例1:
package generic;
//泛型类
class Generic<T> {
private T key;
public void setKey(T key) {
this.key = key;
}
public T getKey() {
return key;
}
}
public class Test {
public static void main(String[] args) {
Generic<String> gen1 = new Generic<String>();
gen1.setKey("XiaoMing");
Generic<String> gen2 = new Generic<String>();
gen2.setKey("LiHua");
String str = gen1.getKey();
System.out.println(str);
Generic<Integer> gen3 = new Generic<Integer>();
gen3.setKey(22);
int value = gen3.getKey();
System.out.println(value);
//对象有多个属性时,用名称1.属性 = 名称2.属性, 将2的该属性的值赋给1的这个属性
//直接用 名称1 = 名称2 赋值时,将2的全部属性都赋值给1
//这里的名称1和名称2是同种类(泛型类时泛型也要相同)的实例对象。
gen1 = gen2;
System.out.println(gen1.getKey());
// gen1 = gen3;//错误,gen1是String类型的类,gen3是Integer类型的类,
//虽然都是Generic类的实例对象,但是泛型不同,不能互相赋值
}
}
注意:同一个类,但是在new()对象时指定的泛型类型不同,这些对象不能相互赋值。
示例2:
package generic;
/**
* 泛型类
* 什么时候定义泛型类?
* 当类中要操作的引用数据类型不确定的时候, 可以使用泛型类来完成.
*
* 泛型类上定义的泛型T, 可以被类内的各个部分使用.
*
* @author 14251
*
*/
class GenericClassDemo<T>{
private String id;
private T info;
GenericClassDemo(String id, T info){
this.id = id;
this.info = info;
}
public void setId(String id) {
this.id = id;
}
public void setInfo(T info) {
this.info = info;
}
public String getId() {
return this.id;
}
public T getInfo() {
return this.info;
}
public void printInfo() {
System.out.println("id: " + this.id + " info: " + this.info);
}
}
class Person{
private String name;
private int age;
Person(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
}
public class GenericClass {
public static void main(String[] args) {
//可以指定泛型为各种引用数据类型
new GenericClassDemo<String>("LiHua", "技术").printInfo();
new GenericClassDemo<Integer>("XiaoMing", 1).printInfo();
new GenericClassDemo<Person>("LiHua", new Person("XiaoHong", 20)).printInfo();
}
}
1. 定义方式:
//定义一个泛型接口
interface Generator<T> {
T next();
}
2. 接口未传入泛型实参时,实现类也要声明成泛型类(类的泛型与接口的泛型相同)。
3. 接口传入了泛型实参时,实现类可以不声明成泛型类(类内相关属性以及方法的类型应与接口的泛型类型相同)。
package generic;
interface GenericInterface<T> {
void show(T t);
}
//类实现接口时指定泛型
class ImpInter1 implements GenericInterface<String>{
public void show(String s) {
System.out.println(s);
}
}
//类实现接口时, 不指定泛型
class ImpInter2<T> implements GenericInterface<T>{
public void show(T t) {
System.out.println(t);
}
}
public class TestInterface{
public static void main(String[] args) {
ImpInter1 imp1 = new ImpInter1();
imp1.show("lalala");
ImpInter2<Character> imp2 = new ImpInter2<Character>();
imp2.show('a');
}
}
什么时候定义泛型方法?
注意:
静态方法不可以访问类上定义的泛型,如需使用泛型,必须定义在方法上。
示例:
package generic;
/**
* 1. 类内的某个方法操作的引用数据类型不确定时, 可以将该方法定义为泛型方法
* 2. 泛型类内可以有与类的泛型不同的泛型方法
*
* 注意:
* 静态方法不可以访问类上定义的泛型, 如需使用泛型, 必须定义在方法上
* @author 14251
*
*/
//泛型类内定义不同于类的泛型的泛型
class GenericMethodDemo<T>{//T是类的泛型, 因此类内所有的T都是相同的
public void showInfo(T t) {//与类的泛型相同
System.out.println("show: " + t);
}
public <Q> void printInfo(Q q) {//定义特有的泛型, Q是局部的, 在该方法外出现的Q与该方法的不同
System.out.println("print: " + q);
}
public static <M> void method(M m) {//泛型不能声明为T(T为类上定义的泛型, 必须使用泛型时需要定义在方法上(M))
System.out.println("method: " + m);
}
}
public class GenericMethod {
public static void main(String[] args) {
//方法的泛型与类相同
new GenericMethodDemo<String>().showInfo("lalala");
new GenericMethodDemo<Integer>().showInfo(4);
//方法的泛型与类不同
GenericMethodDemo<String> g = new GenericMethodDemo<String>();
g.printInfo(8);//传入与类的泛型不同的参数, 调用泛型方法时, 不需要用<>指定泛型
g.printInfo("xixixi");
//静态泛型
GenericMethodDemo.method("hahaha");
}
}
泛型方法与可变参数
/**
* 泛型方法与可变参数
* @param args
*/
public<T> void printMsg(T... args){
for(T t : args){
System.out.println(t);
}
}
以集合为形参的方法,在不确定集合中的数据类型时,可以使用通配符。
package generic;
import java.util.*;
public class TongPeiFu {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<Integer>();
List<String> list2 = new ArrayList<String>();
list1.add(1);
list1.add(3);
list2.add("x");
list2.add("y");
TongPeiFu t = new TongPeiFu();
t.printInfo(list1);
t.printInfo(list2);
}
public void printInfo(List<?> list) { //任何中的的表都可以传入,可以规定只有String类型可以传入(List list)
System.out.println(list);
}
}
extends Person>
(无穷小 , Person],只允许泛型为Person及Person子类的引用调用
super Person >
[Person , 无穷大), 只允许泛型为Person及Person父类的引用调用
extends Comparable>
只允许泛型为实 现Comparable接口的实现类的引用调用
package generic;
import java.util.*;
/**
* 通配符?
* @author 14251
*
*/
class People implements Comparable<People>{
private String name;
private int age;
People(String name, int age){
this.name = name;
this.age = age;
}
public int compareTo(People p) {
int num = this.getName().compareTo(p.getName());
if(num == 0) {
Integer i1 = this.getAge();
Integer i2= p.getAge();
num = i1.compareTo(i2);
}
return num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Worker extends People{
private String factory;
Worker(String name, int age, String factory){
super(name, age);
this.factory = factory;
}
public String getFactory() {
return factory;
}
public void setFactory(String factory) {
this.factory = factory;
}
}
class Teacher extends People{
private String school;
Teacher(String name, int age, String school){
super(name, age);
this.school = school;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
}
//比较器, 降序排列
class Com implements Comparator<People>{//该比较器可以对存储了People类以及其子类的集合排序
public int compare(People o1, People o2) {
int num = o2.getName().compareTo(o1.getName());
if(num == 0) {
Integer i1 = o2.getAge();
Integer i2= o1.getAge();
num = i2.compareTo(i1);
}
return num;
}
}
public class WildCard {
public static void main(String[] args) {
TreeSet<People> tp = new TreeSet<People>(new Com());//People以及其子类都可以传入
//创建集合对象时, 泛型必须明确
// ArrayList> al = new ArrayList>();
// ArrayList extends People> al = new ArrayList extends People>();//默认子类可以传入
tp.add(new People("CB", 18));
tp.add(new People("AC", 20));
tp.add(new People("AB", 19));
tp.add(new People("AC", 20));
TreeSet<Worker> tw = new TreeSet<Worker>(new Com());
tw.add(new Worker("C-B", 18, "-a-"));
tw.add(new Worker("A-C", 20, "-b-"));
tw.add(new Worker("A-B", 19, "-c-"));
tw.add(new Worker("A-C", 20, "-b-"));
TreeSet<Teacher> tt = new TreeSet<Teacher>();
tt.add(new Teacher("C=B", 18, "=a="));
tt.add(new Teacher("A=C", 20, "=b="));
tt.add(new Teacher("A=B", 19, "=c="));
tt.add(new Teacher("A=C", 20, "=b="));
printOut(tp);
System.out.println("--------------------------------");
printOut(tw);
System.out.println("--------------------------------");
printOut(tt);
}
//迭代器
public static void printOut(Set<? extends People> s) {//只能打印People以及其子类的集合
Iterator<? extends People> it = s.iterator();
while(it.hasNext()) {
Object obj = it.next();
if(obj instanceof Worker) {
Worker w = (Worker)obj;
System.out.println("name: "+w.getName()+" age: "+w.getAge()+" factory: "+w.getFactory());
}else if(obj instanceof Teacher) {
Teacher t = (Teacher)obj;
System.out.println("name: "+t.getName()+" age: "+t.getAge()+" school: "+t.getSchool());
}else {
People p = (People)obj;
System.out.println("name: "+p.getName()+" age: "+p.getAge());
}
}
}
}
在某些情况下,一个类的对象是有限而且固定的。例如季节类,只有 4 个对象,这时就可以使用枚举类。
注意:实质是单例设计模式。
package enumexample;
public class Season {
private final String SEASON;
private final String DESCRIPTION;
private Season(String SEASON, String DESCRIPTION) {
this.SEASON = SEASON;
this.DESCRIPTION = DESCRIPTION;
}
private static final Season SPRING = new Season("spring", "春天");
private static final Season SUMMER = new Season("summer", "夏天");
private static final Season AUTUMN = new Season("autumn", "秋天");
private static final Season WINTER = new Season("winter", "冬天");
public static Season getSpring() {
return SPRING;
}
public static Season getSummer() {
return SUMMER;
}
public static Season getAutumn() {
return AUTUMN;
}
public static Season getWinter() {
return WINTER;
}
public void showInfo() {
System.out.println(this.SEASON + " " + this.DESCRIPTION);
}
}
package enumexample;
public class Test {
public static void main(String[] args) {
Season.getSpring().showInfo();
Season.getSummer().showInfo();
Season.getAutumn().showInfo();
Season.getWinter().showInfo();
}
}
package enumexample;
public enum SeasonEnum {
//调用私有构造,实例化枚举对象
SRING("spring", "春天"),
SUMMER("summer", "夏天"),
AUTUMN("autumn", "秋天"),
WINTER("winter", "冬天");
private final String SEASON;
private final String DESCRIPTION;
private SeasonEnum(String SEASON, String DESCRIPTION) {
this.SEASON = SEASON;
this.DESCRIPTION = DESCRIPTION;
}
public void showInfo() {
System.out.println(this.SEASON + " " + this.DESCRIPTION);
}
}
package enumexample;
public class Test {
public static void main(String[] args) {
// SeasonEnum s = SeasonEnum.SRING;
// s.showInfo();
SeasonEnum.SRING.showInfo();
SeasonEnum.SUMMER.showInfo();
SeasonEnum.AUTUMN.showInfo();
SeasonEnum.WINTER.showInfo();
}
}
package enumexample;
public interface EnumInterface {
void printInfo();
}
package enumexample;
public enum SeasonEnum implements EnumInterface{
//调用私有构造,实例化枚举对象
SPRING("spring", "春天"),
SUMMER("summer", "夏天"),
AUTUMN("autumn", "秋天"),
WINTER("winter", "冬天");
private final String SEASON;
private final String DESCRIPTION;
private SeasonEnum(String SEASON, String DESCRIPTION) {
this.SEASON = SEASON;
this.DESCRIPTION = DESCRIPTION;
}
public void showInfo() {
System.out.println(this.SEASON + " " + this.DESCRIPTION);
}
@Override
public void printInfo() {
System.out.println(this.SEASON + " " + this.DESCRIPTION);
}
}
package enumexample;
public class Test {
public static void main(String[] args) {
SeasonEnum.SPRING.showInfo();
SeasonEnum.SUMMER.showInfo();
SeasonEnum.AUTUMN.showInfo();
SeasonEnum.WINTER.showInfo();
}
}