接口
类似与抽象类,但比抽象类要更严格、更抽象它不能有任何的方法实现(体现了多态和高内聚低偶合的设计思想)。
接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected。
接口的字段默认都是 static 和 final 的。
接口多继承,可以继承多个接口,对java单继承机制的补充。
抽象类可以不实现接口方法,普通类必须要实现。
通过接口扩展子类功能
public class InterfaceDemo extends AbstractExample{
public void getInfo(){
System.out.println("必需实现抽象类方法");
}
public void print(){
System.out.println("必需实现接口方法");
}
public static void main(String[] args) {
InterfaceDemo In = new InterfaceDemo();
In.out();
}
}
interface InterfaceExample {
// static final可省略
public static final int X_VALUE = 1;
// abstract 可省略
public abstract void print();
}
abstract class AbstractExample implements InterfaceExample{
public abstract void getInfo();
// 抽象类可以不实现接口方法
public void out(){
System.out.println(InterfaceExample.X_VALUE);
}
}
接口设计不一定是完美的,当实现该接口的子类较多时,接口新增方法就需要每个子类都实现该方法。在jdk1.8之前,为解决这个问题,是通过在接口与子类之间加上一个过渡抽象类来实现的。
jdk1.8后,接口支持了普通方法,但是需要加default声明,同时这个功能属于接口定义加强,接口设计时不考虑。
除此之外,接口还支持了static方法,可以通过接口直接调用.
泛型
通过泛型对参数进行约束,在使用时才确定具体参数类型,防止转换成具体的目标类型出现java.lang.ClassCastException异常
Java 语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型被称为伪泛型, 简单的来说就是在编译时将代码还原成没有泛型的样子,而实际上是直接转化成字节码文件了。
适用于多种数据类型执行相同的代码(代码复用)
静态变量是被泛型类的所有实例所共享的。对于声明为 MyClass的类,访问其中的静态变量的方法仍然是 MyClass.myStaticVar 。不管是通过new MyClass还是 new MyClass创建的对象,都是共享一个静态变量。 泛型无法处理异常类,因为到运行时由于类型擦除的原因无法区分两个异常的具体类型
private static <T extends Number> double add (T a, T b){
System.out.println("a + b = " + (a.doubleValue() + b.doubleValue()));
return a.doubleValue() + b.doubleValue();
}
泛型的基本使用
泛型类
- 简单类型
class Point<T>{ // 此处可以随便写标识符号,T是type的简称
private T var ; // var的类型由T指定,即:由外部指定
public T getVar(){ // 返回值的类型由外部决定
return var ;
}
public void setVar(T var){ // 设置的类型也由外部决定
this.var = var ;
}
}
public class GenericsDemo{
public static void main(String args[]){
Point<String> p = new Point<String>() ; // 里面的var类型为String类型
p.setVar("it") ; // 设置字符串
System.out.println(p.getVar().length()) ; // 取得字符串的长度
}
}
- 多元泛型
class Notepad<K,V>{ // 此处指定了两个泛型类型
private K key ; // 此变量的类型由外部决定
private V value ; // 此变量的类型由外部决定
public K getKey(){
return this.key ;
}
public V getValue(){
return this.value ;
}
public void setKey(K key){
this.key = key ;
}
public void setValue(V value){
this.value = value ;
}
}
public class GenericsDemo{
public static void main(String args[]){
Notepad<String,Integer> t = null ; // 定义两个泛型类型的对象
t = new Notepad<String,Integer>() ; // 里面的key为String,value为Integer
t.setKey("汤姆") ; // 设置第一个内容
t.setValue(20) ; // 设置第二个内容
System.out.print("姓名;" + t.getKey()) ; // 取得信息
System.out.print(",年龄;" + t.getValue()) ; // 取得信息
}
}
泛型接口
interface Info <T>{ // 在接口上定义泛型
public T getInfo();// 定义抽象方法,抽象方法的返回值就是泛型类型
}
class InfoImpl<T> implements Info<T>{// 定义泛型接口的子类
private T var ; // 定义属性
public InfoImpl(T var){ // 通过构造方法设置属性内容
this.setVar(var) ;
}
public void setVar(T var){
this.var = var ;
}
@Override
public T getInfo() {
return this.var;
}
}
public class GenericDemo {
public static void main(String[] args) {
Info<String> info = new InfoImpl<String>("test");
System.out.println("内容:" + info.getInfo()) ;
}
}
泛型方法
泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型\
class的作用就是指明泛型的具体类型,而class类型的变量c,可以用来创建泛型类的对象。
class Food {}
class Fruit extends Food {}
class Apple extends Fruit {}
class Banana extends Fruit{}
class GenericTest {
public void testExtends(List<? extends Fruit> list){
//报错,extends为上界通配符,只能取值,不能放.
//因为Fruit的子类不只有Apple还有Banana,这里不能确定具体的泛型到底是Apple还是Banana,所以放入任何一种类型都会报错
//list.add(new Apple());
//可以正常获取
Fruit fruit = list.get(1);
}
public void testSuper(List<? super Fruit> list){
//super为下界通配符,可以存放元素,但是也只能存放当前类或者子类的实例,以当前的例子来讲,
//无法确定Fruit的父类是否只有Food一个(Object是超级父类)
//因此放入Food的实例编译不通过
list.add(new Apple());
// list.add(new Food());
Object object = list.get(1);
}
}
-
定义泛型方法
-
调用泛型方法
- 限定通配符和非限定通配符
限定通配符对类型进⾏限制,泛型中有两种限定通配符:
表示类型的上界,格式为:<? extends T>,即类型必须为 T类型或者T子类
表示 类型的下界,格式为:<? super T>,即类型必须为T类型或者T的父类
泛型类型必须⽤限定内的类型来进⾏初始化,否则会导致编译错误。
⾮限定通配符表⽰可以⽤任意泛型类型来替代,类型为<T>。
- 上下界限定符extends和super