Java入门学习笔记(九)——抽象类、接口、枚举类Enum、泛型、上界通配符、下界通配符、<?>通配符

一、抽象类

在一个抽象类中,如果只有抽象方法,其他什么都没有,则使用接口更好

注意:

  1. 抽象类必须为public或者protected,缺省为public
  2. 其子类必须实现其所有的抽象方法,否则该子类也是抽象类

二、接口

一个类只有一个父类,但是一个接口可以有多个父接口。

注意:

  1. 接口的数据成员都是public static类型的,缺省时,系统默认处理成pubic static类型;
  2. 接口定义,只需声明,不需实现;
  3. 接口不能实例化;
  4. 同类,接口文件的文件名要与接口名相同。

当接口列表中有多个接口名时,接口名之间可以逗号分隔。

如果只想要实现接口中的部分方法,可以先定义一个抽象类,以抽象类实现这些方法(方法体可以不实现),由该类派生出的类,就可以只实现个别的方法,而不去实现其他方法。

三、枚举类

1.定义枚举类型

package PackageB;

// 定义枚举类型
enum LightColor{
    
    ,绿,}

class TrafficLight1 {
    
    
	// 声明枚举变量
	LightColor lightState;
	public TrafficLight1()
	{
    
    
		// 枚举常量的初始化,为红色
		this.lightState=LightColor.;
	}
	@Override
	public String toString()
	{
    
    
		// 得到枚举常量的名称
		return "当前灯的颜色:"+lightState.name();
	}
	// 改变灯的状态
	public void change()
	{
    
    
		// 返回枚举常量的序数
		int order=lightState.ordinal();
		// 得到所有的枚举常量
		LightColor lightColors[]=LightColor.values();
		order=(order+1)%lightColors.length;
		lightState=lightColors[order];
	}
	public static void  main(String[] args)
	{
    
    
		TrafficLight1 light=new TrafficLight1();
		for(int i=0;i<10;++i)
		{
    
    
			light.change();
		}
		if(light.lightState.equals(LightColor.))
		{
    
    
			System.out.println("现在的颜色:黄");
		}
		else if(light.lightState.equals(LightColor.绿))
		{
    
    
			System.out.println("现在的颜色:绿");
		}
		System.out.println(light);
	}
}

2. 自定义枚举类型

注意:

  1. 自定义枚举类型的构造方法,由private修饰
  2. 自定义枚举类型,首先定义了若干个枚举常量,枚举常量之间用逗号分隔,最后一个枚举常量,需要用分号
  3. 各枚举常量后面圆括号内的实参部分与自定义枚举类型构造方法的形参列表类型一致。

枚举类型的定义

注意,需要单独定义枚举类型的文件。

package PackageB;

import java.util.Random;

enum FigureEnum
{
    
    
	TRIANGLE("三角形",0),
	RECTANGLE("矩形",1),
	CIRCLE("圆形",2);
	String description;
	int order;
	private FigureEnum(String description,int order)
	{
    
    
		this.description=description;
		this.order=order;
	}
	public void setOrder(int order)
	{
    
    
		this.order=order;
	}
	public void setDescription(String description)
	{
    
    
		this.description=description;
	}
	// 返回当前枚举常量的说明部分
	public String getDescription()
	{
    
    
		return description;
	}
	public int getOrder()
	{
    
    
		return order;
	}
	public String getDescription(int order)
	{
    
    
		for(FigureEnum f:FigureEnum.values())
		{
    
    
			if(f.getOrder()==order)
			{
    
    
				return f.getDescription();
			}
		}
		// 这一句是需要添加的,如果不添加,程序会有错误
		// 因为,要保证返回一个String的类型,上面的条件语句中,可能没有满足返回条件
		// 这时,需要添加null的返回值,来保证程序能正常运行
		return null;
	}
	@Override
	public String toString()
	{
    
    
		return name()+"("+description+","+order+")";
	}
	public static FigureEnum getRandomFigureEnum()
	{
    
    
		int order1;
		Random rand=new Random();
		order1=rand.nextInt(FigureEnum.values().length);
		FigureEnum fes[]=FigureEnum.values();
		return fes[order1];
	}
}

测试

package PackageB;

class FigureEnumTest {
    
    
	public static void main(String[] args) {
    
    
		FigureEnum type;
		for (int i = 0; i < 10; ++i) {
    
    
			type=FigureEnum.getRandomFigureEnum();
			switch(type)
			{
    
    
			case TRIANGLE:
				System.out.println("三角形!");
				break;
			case RECTANGLE:
				System.out.println("长方形!");
				break;
			case CIRCLE:
				System.out.println("圆形!");
				break;
			}
		}
	}
}

测试结果

在这里插入图片描述

四、泛型

1.泛型方法的定义

package try_a_package;

import java.util.Date;

class TestGenericFun {
    
    
	public static<T> void fun1(T t)
	{
    
    
		System.out.println("fun1:"+t);
	}
	public static <T> T fun2(T t)
	{
    
    
		System.out.println("fun2:"+t);
		return t;
	}
	public static void main(String[] args)
	{
    
    
		fun1("String");
		fun1(3.1415);
		fun1(new Date());
		String msg=fun2("abcdef");
		System.out.println(msg);
	}
}

2.泛型类的定义

package PackageB;

import java.util.Date;

class Generic1<T> {
    
    
	private T data;
	// 构造方法
	public Generic1(T data)
	{
    
    
		this.data=data;
	}
	// 返回数据
	public T getData()
	{
    
    
		return data;
	}
	@Override
	public String toString()
	{
    
    
		return "dataType:"+data.getClass().getName()+",value:"+data;
	}
	public static void main(String[] args)
	{
    
    
		Generic1<String> g1=new Generic1("张三");
		System.out.println(g1);
		Generic1<Integer> g2=new Generic1(18);
		System.out.println(g2);
		Generic1<Date> g3=new Generic1(new Date());
		System.out.println(g3);
	}
}

在这里插入图片描述

3.通配符

(1)类准备

package try_a_package;

public class Bowl <E>{
    
    
	private E thing;
	public Bowl(E drink)
	{
    
    
		this.thing=drink;
	}
	public Bowl()
	{
    
    
		this.thing=null;
	}
	public E getThing()
	{
    
    
		return thing;
	}
	public void setThing(E thing)
	{
    
    
		this.thing=thing;
	}
	@Override
	public String toString()
	{
    
    
		if(thing!=null)
			return "我是一个碗,装了"+thing;
		else
			return "我是一个碗,但没有东西";
	}
}


package try_a_package;

public class Food {
    
    

}

package try_a_package;

public class Milk extends Drink{
    
    
	@Override
	public String toString()
	{
    
    
		return "牛奶"+"(属于"+super.toString()+")";
	}
}

package try_a_package;

public class Wine extends Drink{
    
    
	@Override
	public String toString()
	{
    
    
		return "酒"+ "(属于"+super.toString()+")";
	}
}

(2)上界通配符

<? extends T>
package try_a_package;

public class TestUpWildcards {
    
    
	public static void main(String[] args)
	{
    
    
		Bowl<Drink> bowl1=new Bowl<>(new Drink());
		System.out.println(bowl1);
		// 下面这句话,没有什么错误,我给的参考书上说,这个有错误。
		//Bowl<Drink> bowl2=new Bowl<>(new Milk());
		// 但我本机运行没有错误,居然得出了正确的结果,没有报错,没有警告。
		// 愣住!!!!!!!!!!!
		// 不知道为啥,作为一个疑惑放到这里,之后深入学习了解以后,再进行修改。
		// 如果有大佬发现哪里有问题,记得告诉我哈》
		Bowl<? extends Drink> bowl2=new Bowl<>(new Milk());
		System.out.println(bowl2);
		Bowl<? extends Drink> bowl3=new Bowl<>(new Drink());
		System.out.println(bowl3);
		bowl2=new Bowl();
		System.out.println(bowl2);
		Wine wine1=new Wine();
		// 那本书上说,下面这一句也有错误??????
		// 我人傻了。
		// 这不正确运行了吗?
		// 以后再看,留个念想,回头再学一遍泛型。
		// 尽信书,不如无书。。。。。。。。。
		//bowl2.setThing(wine1);
		// 好吧,是出错了,我当时因为上面的那个没有改,导致下面这句是出错的。
		
		//wine1=(Wine)bowl3.getThing();
		// 可能注释错位置了,是上面那句出错了
		// 抛出了一个异常:
		// Exception in thread "main" java.lang.ClassCastException: class try_a_package.Milk cannot be cast to class try_a_package.Wine (try_a_package.Milk and try_a_package.Wine are in module hello_world_try of loader 'app')
		//		at hello_world_try/try_a_package.TestUpWildcards.main(TestUpWildcards.java:27)
		
		
	}
}

(3)下界通配符

<? extends T>
package try_a_package;

public class TestLowWildcards {
    
    
	public static void main(String[] args)
	{
    
    
		Bowl<? super Milk> bowl1=new Bowl<> (new Milk());
		// 原本是装牛奶的碗
		System.out.println(bowl1);
		Milk milk1=new Milk();
		bowl1.setThing(milk1);
		//milk1=bowl1.getThing();
		// 该句有错误
		System.out.println(milk1);
		// 可以改装饮料(上一级)
		bowl1=new Bowl<>(new Drink());
		System.out.println(bowl1);
		// 也可以改装酒(同级)
		bowl1=new Bowl<>(new Wine());
		System.out.println(bowl1);
		bowl1=new Bowl<>(new Food());
		// 这个没有定义确切的内容?
		System.out.println(bowl1);
	}
} 

(4)通配符<?>

可以指代任何类
不能通过setXX方法来赋值,但可以通过调用该类的getXX方法,得到属性值,但其数据类型是CAP#1,因而不能直接引用。
只有将其强制转换成相应的数据类型之后,才可以给其他变量赋值。

扫描二维码关注公众号,回复: 12384274 查看本文章
package try_a_package;

public class TestWildcards {
    
    
	public static void main(String[] args)
	{
    
    
		Bowl<?>bowl1=new Bowl<>(new Milk());
		System.out.println(bowl1);
		Milk milk1=(Milk) bowl1.getThing();
		System.out.println(milk1);
		Drink drink=(Drink)bowl1.getThing();
		System.out.println(drink);
		Object ob=bowl1.getThing();
		System.out.println(ob);
		milk1=new Milk();
		System.out.println(milk1);
	}
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41563270/article/details/108894161