java记录,泛型和接口的使用
接口
接口是抽象类的延伸,可以将接口看作是纯粹的抽象类,接口中的所有方法都没有方法体。接口使用interface关键字进行定义:
public interface MyList{
int size();
boolean isEmpty();
boolean contains(int o);
boolean add(int o);
}
接口可以像类一样被权限修饰符修饰,但public关键字仅限用于接口在与其同名的文件中被定义。
一个类实现一个接口可以使用 implement 关键字:
public class MyLinkedList implements MyList{
}
Notice:在接口中定义的方法必须被定义为public 或者 abstract 形式,其他修饰权限不被java编译器认可,接口中不将该方法声明为public形式,方法默认也是public形式。
但是在类中实现接口时,对接口中的方法体进行编写,必须将接口方法声明为public形式,若不加上public则会报错。
补充:在接口中定义的任何字段都自动是static 和 final的。
接口与继承:
java中不允许多重继承,即类的父类只能唯一。但是接口可以实现多重继承,因为一个类可以同时实现多个接口。可以将所有需要继承的接口放置在 implement 关键字后并使用逗号隔开。(可能会产生巨大的代码量,因为必须在类中实现所有接口中的方法)。
格式如下:
class 类名 implements 接口1,接口2,接口3,...,接口 n
注意,接口之间的继承也使用 extends 关键字:
interface intf1{
}
interface intf2 extends intf1{
}
泛型
泛型实际上就是使程序员定义安全的类型。为什么说是定义安全的类型呢。
因为在泛型出现之前,java也提供了对object的引用“任意化”操作,这种“任意化”操作就是对object引用进行向下转型和向上转型操作,但某些强制类型转换的错误也许不会被编译器捕捉,而在运行后出现异常,为了消除这种安全隐患,java提供了泛型。
1.在定义泛型类时,可以声明多个定义类型:
class Example<T1,T2>
T1,T2为可能被定义的类型。
这样在该类中实例化对象时,就可以指定多个类型:
Example<Boolean,Double> exp1 = new Example<Boolean,Double>();
2.定义泛型类时声明数组类型
public class ArrayClass<T>{
private T[] array;
public voidsetArray(T[] array){
this.array = array;
}
public T[] getArray(){
return array;
}
}
public static void main(String[] args){
ArrayClass<Integer> a = new ArrayClass<Integer>();
Integer[] array = {1,2,3};
a.setArray(array);
}
Notice:不可以使用泛型来建立数组的实例:
T[] array = new T[10];
上述代码是错误的。
3.集合类声明容器的元素
泛型的高级用法
泛型的高级用法包括限制泛型可用类型和使用类型通配符等。
1.限制泛型可用类型
语法如下:
class 类名 <T extends anyClass>
其中,anyClass 代表某个接口或类。
在使用泛型限制后,泛型类的类型必须实现或继承了 anyClass 这个接口或类。无论 anyClass 是 接口还是类,都使用 extends 关键字。
2.使用类型通配符
在泛型机制中,提供了类型通配符,其主要作用是在创建一个泛型类对象时,限制这个泛型类的类型实现或继承某个接口或类的子类。要声明这样一个对象可以使用“?”通配符来表示,同时使用extends关键字来对泛型加以限制。
使用泛型类型通配符的语法如下:
泛型类名称<? extends List> a = null;
其中,<? extends List> 表示类型未知,当需要使用该泛型对象时,可以单独实例化(List 就是要实现的接口)。
还可以将该实例放置在方法的参数中。
如果使用 A<?> 这种形式实例化泛型类对象,则默认表示可以将A指定为实例化Object及以下的子类类型。
在泛型中使用通配符形式:
List<String> l1 = new ArrayList<String>();//实例化一个 ArrayList对象
l1.add("Member"); // 在集合中添加内容
List<?> l2 = l1; //使用通配符
List<?> l3 = new LinkedList<Integer>();
System.out.println(l2.get(0)); //获取集合中的第一个值
List<?>类型的对象可以接受String类型的ArrayList集合,也可以接受Integer类型的LinkedList集合。
那么
List<?> l2 = l1 语句
和
List l2 = l1 语句 存在何种区别呢?
使用通配符声明的名称实例化的对象不能对其加入新的信息,只能获取或者删除。
如:
l1.set(0,"member change");//没使用通配符的对象可以调用set()方法
//l2.set(0,"member change");使用通配符的对象不可以调用
//l3.set(0,1);
l2.get(0); //可以使用l2的实例获取集合中的值
l2.remove(0);//根据键名删除集合中的值
泛型类型限制出了可以向下限制之外,还可以进行向上限制,只要在定义的时候使用super关键字即可。
如。“A<? super List> a = null;” 这样定义后,对象a只接受List接口或上层父类类型,如“a = new A< Object >();”
3.继承泛型类与实现泛型接口
public class ExtendsClass<T1>{
}
class SubClass<T1,T2,T3>extends ExtendsClass<T1>{
}
如果在SubClass类继承ExtendsClass类时保留父类的泛型类型,需要在继承时指明,若不指明,则SubClass类中的T1、T2、T3都会自动变为Object,所以一般情况下保留父类的泛型类型。
实现泛型接口:
public interface MyList<T>
{
int size();
boolean isEmpty();
boolean contains(T o);
boolean add(T o);
}
总结:
1.泛型的类型参数只能是类类型,不可以是简单类型,如 A < int > 这种泛型定义就是错误的。
2.泛型的类型个数可以是多个。
3.可以使用extends关键字限制泛型类型。
4.可以使用通配符限制泛型类型。
附上使用接口和泛型自己重新定义的MyLinkedList类:
-----MyList.java-----
package homework5;
public interface MyList<T>
{
int size();
boolean isEmpty();
boolean contains(T o);
boolean add(T o);
}
-----MyLinkedList.java-----
package homework5;
import java.util.Random;
class Node<T>
{
T value;
Node<T> next;
public Node(T i)
{
value = i;
next = null;
}
}
public class MyLinkedList<T> implements MyList<T> {
Node<T> head;
public MyLinkedList()
{
}
public MyLinkedList(T... values)
{
if(values.length == 0)
return;
head = new Node<T>(values[0]);
Node<T> pre = head;
for(int i=1; i<values.length; i++)
{
Node<T> node = new Node<T>(values[i]);
pre.next = node;
pre = node;
}
}
public void addToHead(T i)
{
Node<T> node = new Node<T>(i);
node.next = head;
head = node;
}
public void addToTail(T i)
{
if (head == null)
{
head = new Node<T>(i);
return;
}
Node<T> tail = head;
while(tail.next != null)
{
tail = tail.next;
}
Node<T> node = new Node<T>(i);
tail.next = node;
}
public String toString()
{
String str = "";
Node<T> node = head;
while(node != null)
{
str += String.format("%d--> ", node.value);
node = node.next;
}
return str;
}
//
@Override
public int size()
{
int count = 0;
Node<T> temp = head;
while(temp!= null)
{
count++;
temp = temp.next;
}
return count;
}
//
@Override
public boolean isEmpty()
{
return head == null;
}
//
@Override
public boolean contains(T o) {
boolean find = false;
Node<T> temp = head;
if(o == null)
{
return find;
}
while(temp!= null)
{
if(temp.value.equals(o))
{
find = true;
}
temp = temp.next;
}
return find;
}
//
@Override
public boolean add(T o) {
boolean judge = false;
if(o == null)
return judge;
addToHead(o);
judge = true;
return judge;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
MyLinkedList<Integer> l = new MyLinkedList<Integer>();
Random rd = new Random();
for(int i=1; i<10; i++)
{
l.addToTail(rd.nextInt(100));
}
l.addToTail(200);
l.addToHead(200);
System.out.println(l);
System.out.println(l.size());
System.out.println(l.isEmpty());
System.out.println(l.contains(200));
System.out.println(l.contains(null));
System.out.println(l.add(222));
System.out.println(l);
l = new MyLinkedList(1, 2, 3, 4);
System.out.println(l);
System.out.println(l.size());
System.out.println(l.size());
System.out.println(l.isEmpty());
System.out.println(l.contains(200));
System.out.println(l.contains(null));
System.out.println(l.add(null));
System.out.println(l);
}
}
以及输出: