嵌入式之路,贵在日常点滴
---阿杰在线送代码
目录
问题:如果我们需要产生多个对象,每个对象的逻辑完全一样,只要对象内的成员变量的类型不同,那我们如何去做?
缺点:这种方式会导致类的膨胀,重用型太差。
-
- 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());
- }
- }
运行结果:
10
ajie
缺点,编译的时候正常,但运行的时候可能会异常。 (因为其类型比较模糊,有时候做了错误得类型转换就会导致运行程序时崩溃,编译没有错误)
鼠标定位到数据类型,右键 选择 Type Hierarchy
观察可以看出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 a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T 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());
- }
- }
运行结果:
10
ajie
myeclipse工程环境出错:Set project compiler compliance settings to '1.5'
- class Cls1
- {
- 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 = new Cls1>(new Cls1(10)); - System.out.println(cls1.getData().getData());
-
- }
- }
运行结果:
10
- class Cls2
- {
- 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
cls3 = new Cls2(100,"ajie"); - System.out.println(cls3.getData());
- System.out.println(cls3.getData2());
- System.out.println(cls3.getData()+cls3.getData2());
-
- Cls2
cls4 = new Cls2(100,10); - System.out.println(cls4.getData()+cls4.getData2());//注意,在以前我们这里用到的+都是链接作用
- //在这里+可以作为加法使用
- int sum = 0;
- sum = cls4.getData()+cls4.getData2();
- System.out.println(sum);
- }
- }
运行结果:
100
ajie
100ajie
110
110
- abstract class Cls1
- {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
-
- abstract void printInfo();
- }
-
- class Cls2
extends Cls1 - {
- 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
cls = new Cls2(10,"ajie"); - System.out.println(cls.getData());
- System.out.println(cls.getData2());
- cls.printInfo();
- }
- }
运行结果:
10
ajie
- abstract class Cls1
- {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
-
- abstract void printInfo();
- }
-
- interface Cls3
- {
- abstract void printInfoCls3(T t);
- }
-
- class Cls2
extends Cls1 implements Cls3 - {//如果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
cls = new Cls2(10,"ajie"); - System.out.println(cls.getData());
- System.out.println(cls.getData2());
- cls.printInfo();
- cls.printInfoCls3(100);
- }
- }
运行结果:
10
ajie
100
如何解决 如果Cls2的T和Cls3的T是同名,则在下面主函数使用时,Cls3的T类型遵循Cls2,否则会报错 问题。即使不同名,也会报错
- abstract class Cls1
- {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
-
- abstract void printInfo();
- }
-
- interface Cls3
- {
- abstract void printInfoCls3(T3 t);
- }
-
- class Cls2
extends Cls1 implements Cls3 - {//如果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
cls = new Cls2(10,"ajie"); - System.out.println(cls.getData());
- System.out.println(cls.getData2());
- cls.printInfo();
- cls.printInfoCls3("ajie");
- }
- }
在定义泛型类别时,默认在实例化泛型类的时候可以使用任何类型,但是如果想要限制使用泛型类型时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口。
当没有指定泛型继承的类型或接口时,默认使用extends Object。所以默认情况下任何类型都可以作为参数传入。
- //默认情况下,以下两种情况是一样的
- class Cls1
- {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
- }
-
- class Cls1
- {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
- }
- //使用extends关键字指定这个类型
-
- abstract class Cls1
- {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
-
- abstract void printInfo();
- }
-
- interface Cls3
- {
- abstract void printInfoCls3(T3 t);
- }
-
- class Cls2
extends Cls1 implements Cls3 - {
- 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 a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
-
- abstract void printInfo();
- }
-
- interface Cls3
- {
- abstract void printInfoCls3(T3 t);
- }
-
- class Cls2
extends Cls1 implements Cls3 - {
- 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
//但是在泛型这里需要使用extends限定 - {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
-
- abstract void printInfo();
- }
-
- interface Cls3
- {
- abstract void printInfoCls3(T3 t);
- }
-
- class Cls2
extends Cls1 implements Cls3 - {
- 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
c1 = new Cls1(); - Cls1
c2 = new Cls1(); - c1 = c2;//发生编译错误
-
- Cls1
- c3 = c2;//c3和c2类型同样不兼容,也会发生编译错误
泛型类实例之间的不兼容性会带来使用的不便。我们可以使用泛型通配符(?)声明泛型类的变量就可以解决这个问题。
- class Animal
- {
-
- }
-
- class Dog extends Animal
- {
-
- }
-
-
- class Cls1
- {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- Cls1
c1 = new Cls1(10); - Cls1
c2 = new Cls1(10.0); - Cls1> c3;
-
- c3 = c1;
- c3 = c2;
- }
- }
- class Animal
- {
-
- }
-
- class Dog extends Animal
- {
-
- }
-
-
- class Cls1
- {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- Cls1
c1 = new Cls1(new Dog()); - Cls1 extends Animal> c2;
-
- c2 = c1;
- }
- }
- class Animal
- {
-
- }
-
- class Dog extends Animal
- {
-
- }
-
-
- class Cls1
- {
- T a;
-
- public Cls1(T a){
- this.a = a;
- }
-
- public T getData(){
- return a;
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- Cls1
c1 = new Cls1(new Dog()); - Cls1 super Dog> c2;
- //Cls1
c1 = new Cls1(new Dog()); - //Cls1 super Dog> c2;
- c2 = c1;
- }
- }
- 访问修饰符 <泛型列表> 返回类型 方法名(参数列表){
- 实现代码
- }
提示: 是否拥有泛型方法与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。
- class A
- {
- public void printInfo(T t){
- System.out.println(t);
- }
- }
-
- class B
- {
- public
void printInfo(T t){ - System.out.println(t);
- }
- }
-
- public class Test {
- public static void main(String[] args) {
- A
a = new A(); - a.printInfo("ajie");//此泛型中的方法参数类型被类的泛型类型限制住
-
- B b = new B();
- b.printInfo("ajiezaixian");//泛型方法不应该被类的泛型类型限制住
- b.printInfo(1234);
- b.printInfo(0.5);
- }
- }
运行结果:
ajie
ajiezaixian
1234
0.5
- class A
- {
- public void printInfo(T t){
- System.out.println(t);
- }
- }
-
- class B
- {
- //泛型方法
- public
void printInfo(T t){ - System.out.println(t);
- }
- //泛型方法的重载
- public
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
a = new A(); - a.printInfo("ajie");//此泛型中的方法参数类型被类的泛型类型限制住
-
- B b = new B();
- b.printInfo("ajiezaixian");//泛型方法不应该被类的泛型类型限制住
- b.printInfo(1234);
- b.printInfo(0.5);//比方法重载好用多了
-
- b.printInfo("ajie", "这是泛型方法的重载");
- }
- }
运行结果
ajie
ajiezaixian
1234
0.5
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
void printInfo(T t){ - System.out.println(t);
- }
-
- public static
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());
- }
- }
运行结果:
啃骨头
吃鱼肉
动物吃
啃骨头