问题:如果我们需要产生多个对象,每个对象的逻辑完全一样,只要对象内的成员变量的类型不同,那我们如何去做?
-
创建多个类文件,给每个类中的成员变量设置指定的数据类型。
class Cls1
{
int a;
public Cls1(int a){
this.a = a;
}
public int getData(){
return a;
}
}
class Cls2
{
String a;
public Cls2(String a){
this.a = a;
}
public String getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1 cls1 = new Cls1(10);
System.out.println(cls1.getData());
Cls2 cls2 = new Cls2("ajie");
System.out.println(cls2.getData());
}
}
-
创建一个类文件,给这个类中的成员变量设置Object数据类型。
class Cls1
{
Object a;
public Cls1(Object a){
this.a = a;
}
public Object getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1 cls1 = new Cls1(10);
System.out.println(cls1.getData());
Cls1 cls2 = new Cls1("ajie");
System.out.println(cls2.getData());
}
}
一、泛型简介
-
泛型可以在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的。
-
泛型的原理就是"类型的参数化",即把类型看作参数。也就是说把所要操作的数据类型看作参数,就像方法的形式参数是运行时传递的值的占位符一样。
-
简单的说,类型变量扮演的角色就如同一个参数,它提供给编译器用来类型检查的信息。
-
泛型可以提高代码的扩展性和重用性。
class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Integer> cls1 = new Cls1<Integer>(10);
System.out.println(cls1.getData());
Cls1<String> cls2 = new Cls1<String>("ajie");
System.out.println(cls2.getData());
}
}
二、泛型类及特点
1、泛型的类型参数可以是泛型类
class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Cls1<Integer>> cls1 = new Cls1<Cls1<Integer>>(new Cls1<Integer>(10));
System.out.println(cls1.getData().getData());
}
}
2、泛型类可以同时设置多个类型参数
class Cls2<T,T2>
{
T a;
T2 b;
public Cls2(T a,T2 b){
this.a = a;
this.b = b;
}
public T getData(){
return a;
}
public T2 getData2(){
return b;
}
}
public class Test {
public static void main(String[] args) {
Cls2<Integer,String> cls3 = new Cls2<Integer,String>(100,"ajie");
System.out.println(cls3.getData());
System.out.println(cls3.getData2());
System.out.println(cls3.getData()+cls3.getData2());
Cls2<Integer,Integer> cls4 = new Cls2<Integer,Integer>(100,10);
System.out.println(cls4.getData()+cls4.getData2());//注意,在以前我们这里用到的+都是链接作用
//在这里+可以作为加法使用
int sum = 0;
sum = cls4.getData()+cls4.getData2();
System.out.println(sum);
}
}
3、泛型类可以继承泛型类
abstract class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printInfo();
}
class Cls2<T,T2> extends Cls1<T>
{
T2 b;
public Cls2(T a,T2 b){
super(a);//调用了父类的构造方法,这个语句必须放在子类构造方法的第一句
this.b = b;
}
public T2 getData2(){
return b;
}
@Override
void printInfo() {
// TODO Auto-generated method stub
System.out.println("print");
}
}
public class Test {
public static void main(String[] args) {
Cls2<Integer,String> cls = new Cls2<Integer,String>(10,"ajie");
System.out.println(cls.getData());
System.out.println(cls.getData2());
cls.printInfo();
}
}
4、泛型类可以实现泛型接口
abstract class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printInfo();
}
interface Cls3<T>
{
abstract void printInfoCls3(T t);
}
class Cls2<T,T2> extends Cls1<T> implements Cls3<T>
{//如果Cls2的T和Cls3T是同名,则在下面主函数使用时,Cls3的类型遵循Cls2,否则会报错
//即使不同名,也会报错 问题如何解决 在下面展示
T2 b;
public Cls2(T a,T2 b){
super(a);//调用了父类的构造方法,这个语句必须放在子类构造方法的第一句
this.b = b;
}
public T2 getData2(){
return b;
}
@Override
void printInfo() {
// TODO Auto-generated method stub
System.out.println("print");
}
@Override
public void printInfoCls3(T t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
public class Test {
public static void main(String[] args) {
Cls2<Integer,String> cls = new Cls2<Integer,String>(10,"ajie");
System.out.println(cls.getData());
System.out.println(cls.getData2());
cls.printInfo();
cls.printInfoCls3(100);
}
}
abstract class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printInfo();
}
interface Cls3<T3>
{
abstract void printInfoCls3(T3 t);
}
class Cls2<T,T2,T3> extends Cls1<T> implements Cls3<T3>
{//如果Cls2的T和Cls3T是同名,则在下面主函数使用时,Cls3的类型遵循Cls2,否则会报错
T2 b;
public Cls2(T a,T2 b){
super(a);//调用了父类的构造方法,这个语句必须放在子类构造方法的第一句
this.b = b;
}
public T2 getData2(){
return b;
}
@Override
void printInfo() {
// TODO Auto-generated method stub
System.out.println("print");
}
@Override
public void printInfoCls3(T3 t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
public class Test {
public static void main(String[] args) {
Cls2<Integer,String,String> cls = new Cls2<Integer,String,String>(10,"ajie");
System.out.println(cls.getData());
System.out.println(cls.getData2());
cls.printInfo();
cls.printInfoCls3("ajie");
}
}
三、限制泛型可用类型
//默认情况下,以下两种情况是一样的
class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
class Cls1<T extends Object>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
//使用extends关键字指定这个类型
abstract class Cls1<T extends String>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printInfo();
}
interface Cls3<T3>
{
abstract void printInfoCls3(T3 t);
}
class Cls2<T extends String,T2,T3> extends Cls1<T> implements Cls3<T3>
{
T2 b;
public Cls2(T a,T2 b){
super(a);//调用了父类的构造方法,这个语句必须放在子类构造方法的第一句
this.b = b;
}
public T2 getData2(){
return b;
}
@Override
void printInfo() {
// TODO Auto-generated method stub
System.out.println("print");
}
@Override
public void printInfoCls3(T3 t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
//使用extends关键字指定这个类型必须是继承某个类
class Animal
{
}
class Dog extends Animal
{
}
abstract class Cls1<T extends Animal>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printInfo();
}
interface Cls3<T3>
{
abstract void printInfoCls3(T3 t);
}
class Cls2<T extends Animal,T2,T3> extends Cls1<T> implements Cls3<T3>
{
T2 b;
public Cls2(T a,T2 b){
super(a);//调用了父类的构造方法,这个语句必须放在子类构造方法的第一句
this.b = b;
}
public T2 getData2(){
return b;
}
@Override
void printInfo() {
// TODO Auto-generated method stub
System.out.println("print");
}
@Override
public void printInfoCls3(T3 t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
//使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口。
interface Move
{
abstract void test();
}
class A implements Move//正常继承实现接口的方法使用的是implements
{
public void test(){
}
}
abstract class Cls1<T extends Move>//但是在泛型这里需要使用extends限定
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
abstract void printInfo();
}
interface Cls3<T3>
{
abstract void printInfoCls3(T3 t);
}
class Cls2<T extends Move,T2,T3> extends Cls1<T> implements Cls3<T3>
{
T2 b;
public Cls2(T a,T2 b){
super(a);//调用了父类的构造方法,这个语句必须放在子类构造方法的第一句
this.b = b;
}
public T2 getData2(){
return b;
}
@Override
void printInfo() {
// TODO Auto-generated method stub
System.out.println("print");
}
@Override
public void printInfoCls3(T3 t) {
// TODO Auto-generated method stub
System.out.println(t);
}
}
四、类型通配的方式
Cls1<Integer> c1 = new Cls1<Integer>();
Cls1<String> c2 = new Cls1<String>();
c1 = c2;//发生编译错误
Cls1<Object> c3 = c1;//c3和c1类型并不兼容,发生编译错误
c3 = c2;//c3和c2类型同样不兼容,也会发生编译错误
类型通配声明 例子
类型通配的方式
-
"?"代表任意一个类型
class Animal
{
}
class Dog extends Animal
{
}
class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Integer> c1 = new Cls1<Integer>(10);
Cls1<Double> c2 = new Cls1<Double>(10.0);
Cls1<?> c3;
c3 = c1;
c3 = c2;
}
}
- 和限制泛型的上限相似,同样可以使用extends关键字限定通配符匹配类型的上限
class Animal
{
}
class Dog extends Animal
{
}
class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Dog> c1 = new Cls1<Dog>(new Dog());
Cls1<? extends Animal> c2;
c2 = c1;
}
}
-
还可以使用super关键词限定通配符匹配类型的下限
class Animal
{
}
class Dog extends Animal
{
}
class Cls1<T>
{
T a;
public Cls1(T a){
this.a = a;
}
public T getData(){
return a;
}
}
public class Test {
public static void main(String[] args) {
Cls1<Dog> c1 = new Cls1<Dog>(new Dog());
Cls1<? super Dog> c2;
//Cls1<Animal> c1 = new Cls1<Animal>(new Dog());
//Cls1<? super Dog> c2;
c2 = c1;
}
}
五、泛型方法
-
不仅类可以声明泛型,类中的方法也可以声明仅用于自身的泛型,这种方法叫做泛型方法。其定义格式为:
访问修饰符 <泛型列表> 返回类型 方法名(参数列表){
实现代码
}
-
在泛型列表中声明的泛型,可用于该方法的返回类型声明、参数类型声明和方法代码中的局部变量的类型声明。
-
类中的其他方法不能使用当前方法声明的泛型。
class A<T>
{
public void printInfo(T t){
System.out.println(t);
}
}
class B
{
public <T> void printInfo(T t){
System.out.println(t);
}
}
public class Test {
public static void main(String[] args) {
A<String> a = new A<String>();
a.printInfo("ajie");//此泛型中的方法参数类型被类的泛型类型限制住
B b = new B();
b.printInfo("ajiezaixian");//泛型方法不应该被类的泛型类型限制住
b.printInfo(1234);
b.printInfo(0.5);
}
}
class A<T>
{
public void printInfo(T t){
System.out.println(t);
}
}
class B
{
//泛型方法
public <T> void printInfo(T t){
System.out.println(t);
}
//泛型方法的重载
public <T,T2> void printInfo(T t,T2 t2){
System.out.println(t);
System.out.println(t2);
//System.out.println(t+t2);会报错 只有实例化确定类型后才让加 跟我们之前遇到的要区分开
}
}
public class Test {
public static void main(String[] args) {
A<String> a = new A<String>();
a.printInfo("ajie");//此泛型中的方法参数类型被类的泛型类型限制住
B b = new B();
b.printInfo("ajiezaixian");//泛型方法不应该被类的泛型类型限制住
b.printInfo(1234);
b.printInfo(0.5);//比方法重载好用多了
b.printInfo("ajie", "这是泛型方法的重载");
}
}
什么时候使用泛型方法,而不是泛型类呢?
class Animal
{
public void eat(){
System.out.println("动物吃");
}
}
class Dog extends Animal
{
public void eat(){
System.out.println("啃骨头");
}
}
class Cat extends Animal
{
public void eat(){
System.out.println("吃鱼肉");
}
}
class B
{
//泛型方法
public <T> void printInfo(T t){
System.out.println(t);
}
public static<T extends Animal> void printInfo(T t){
t.eat();
}
}
public class Test {
public static void main(String[] args) {
B b = new B();
b.printInfo(new Dog());
b.printInfo(new Cat());
b.printInfo(new Animal());
B.printInfo(new Dog());
}
}
评论(0)
您还未登录,请登录后发表或查看评论