泛型
概念:
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质:
是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数.
泛型的运用:
这种参数类型可以用在
类
、接口
和方法
中,分别被称为泛型类、泛型接口、泛型方法。
泛型的定义:
泛型的定义很简单,只要在原来的 接口 、类 上使用
<>
的语法就可以产生 泛型接口、泛型类。
不写泛型的时候(为了先下兼容),认为元素类型就是Object,
等价于 ArrayList
代码演示如下:
ArrayList arrayList = new ArrayList();
arrayList.add("hello");
arrayList.add("world");
arrayList.add(10);//Integer -> 装箱操作
再理解:
问题就在于消费集合元素时,
无法确定
元素的类型。只能在运行时暴露异常信息。
为了解决此问题,Java语言就提供了泛型
的技术,用来约束
集合中元素的类型。
并且它会将异常提前
到编译期。
演示自己定义一个泛型类:
尖括号中的标识符
是自己起的,数量没有限制,用逗号
分隔就行.
只是从实践中,大家会使用一些见名知意的泛型标识:
E-----element
T----- type
Pk---- 主键
有了泛型定义以后,所有类中出现类型的地方(成员类型、方法返回值、方法参数)可以直接使用泛型标识
代码演示:
class Class<T>{
}
class Class2<T,M>{
private T age;
public T getAge() {
return age;
}
public void setAge(T age) {
this.age = age;
}
public void method1(M m){
System.out.println(m);
}
}
public class Demo {
public static void main(String[] args) {
//即使你是一个泛型类,也可以不指定泛型类型(默认就是Object)
Class2 class2 = new Class2();
class2.setAge("hello");
Object age = class2.getAge();
class2.method1("hello");
//当在代码中提供了泛型以后,就可以使用泛型带来的好处
// 类型绑定,将对应的类型确定下来
Class2<Integer,String> clazz2 = new Class2<Integer, String>();
//jdk 1.7 支持泛型推断
Class2<Integer,String> clazz3 = new Class2<>();
// clazz2.setAge("hello");//报错,编译期错误.
clazz2.setAge(10);
System.out.println(clazz2.getAge());
clazz2.method1("1111");
}
}
其实即使是一个普通的Java类(非泛型类),也支持在类中定义泛型方法。
格式:
修饰符 <T> 返回值类型 方法名(参数类型 参数名,.....){
}
具体T的绑定,可以出现在: 返回值类型、参数类型上。
代码演示:
public class Demo {
public static void main(String[] args) {
DemoMethod.eq("aaa", 10);
Object o = DemoMethod.m2(2, 3);
}
}
class DemoMethod{
public static <T> boolean eq(T a,T b){
return a==b;
}
public static <T> T m2(Integer a,Integer b ){
return (T)null;
}
}
6.1 排序
static <T extends Comparable<? super T>> void java.util.Collections.sort(List elements,[new Comparator(){ public int compare(T o1, T o2){return …} } ]) 对列表元素排序
6.2 查找
static <T extends Comparable<? super T>> int java.util.Collections.binarySearch(List elements, T key) 二分查找key,返回对象索引
6.3 其他
static java.util.Collections.min(Collection elements, Comparator<? super T> c)
static java.util.Collections.max(Collection elements, Comparator<? super T> c)
查找最小值/最大值
三、并发部分API
java.lang.Runnable
void run() 必须覆盖这个方法
java.lang.Thread
Thread()
Thread(Runnable target) 构造器
void start() 启动线程
void run() 如果没有重写,调用关联Runnable的run方法
void interupt() 中断线程(中止阻塞状态,对运行线程无作用)
void setPriority(int newPriority) 设置优先级(1-10,默认5)
static void yield()
static void sleep(long millis) 使当前线程处于让步状态(让步于同优先级或高优先级线程)
休眠
void setDaemon() 设置为守护线程
Thread.State getState() 获得线程当前状态
锁对象
ReentrantLock myLock = new ReentrantLock();
mylock.lock();
try{
critical section
}finally{
mylock.unlock();
}
条件对象
private ReetranLock mylock = new ReetranLock();
private Condition sufficientFunds = mylock.newCondition()
public void transfer(int from, int amount)
{
mylock.lock();
try{
while(account[from] < amount){
sufficientFunds.await();
}
…
sufficientFunds.singalAll();
}finally{
mylock.unlock();
}
}
synchronized关键字(内置锁)
格式1:synchronized 方法
格式2:synchronized(obj){}
使用synchronized如何设置条件变量
void notifyAll() 解除在对象上调用wait方法的线程的阻塞状态
void wait() 导致线程进入等待状态
volatile域
volatile只提供可见性(在线程工作内存中被修改后立即写入到主存中),不提供原子性。
使用final变量可以保证可见性:构造函数完成时即不变,未完成构造期间对其他线程不可见。
java.lang.ThreadLocal
作用:将内存共享变量变为线程拷贝变量
Executor类执行器
1)调用Executors类(工厂类)中静态工厂方法newCacherThreadPool
2)调用submit提交Runnable或Callable对象
3)当不再提交任何任务时,调用shutdown