泛型
- 泛型的好处:
- 编译时,检查添加元素的类型,提高了安全性
- 减少了类型转换的次数,提高效率
- 不再提示编译警告
- 介绍:
- 泛型又称参数化类型,是JDK5.0出现的新特性,解决数据类型的安全性问题
- 在类声明或实例化时只要指定好需要的具体的类型即可
- java泛型可以保证如果程序在编译时没有发出警告,运行时就不会发生ClassCastException异常。同时,代码更加简洁,健壮
- 泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型。
- 泛型的声明:
- interface 接口 {} 和class 类<K,V>{}
- 其中,T,K,V不代表值,而是表示类型
- 任意字母都可以。常用T表示,是Type的缩写
- 泛型的实例化:
- 要在类名后面指定类型参数的值(类型)。如:
- List strList = new ArrayList();
- Iterator iterator = customers.iterator();
- 泛型使用的注意事项和细节:
- interface List{} , public class HashSet{} 等等 说明:T,E 只能是引用类型
- 在指定泛型具体类型后,可以传入该类型或者其子类类型
- 泛型使用形式:
- Listlist1 =new ArrayList();
- Listlist2 = new ArrayList<>();
- 如果我们这样写 List list3 = new ArrayList();默认给它的泛型是[ E就是 Object]
自定义泛型类
- 基本语法:
- class 类名 <T,R…>{ //…表示可以有多个泛型成员}
- 注意细节:
- 普通成员可以使用泛型(属性,方法)
- 使用泛型的数组,不能初始化
- 静态方法中不能使用类的泛型
- 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
- 如果在创建对象时,没有指定类型,默认为Object
自定义泛型接口
- 基本语法:
- interface 接口名 <T,R…>{ }
- 注意细节:
- 接口中,静态成员也不能使用泛型(这个和泛型类规定一样)
- 泛型接口的类型,在继承接口或者实现接口时确定
- 没有指定类型,默认为Object
自定义泛型方法
- 基本语法:
- 修饰符<T,R…> 返回类型 方法名(参数列表){ }
- 注意细节:
- 泛型方法,可以定义在普通类中,也可以定义在泛型类中
- 当泛型方法被调用时,类型会确定
- public void eat(E e){ }, 修饰符后没有<T,R…>eat方法不是泛型方法,而是使用了泛型
泛型的继承和通配符
-
说明:
-
泛型不具备继承性
List list = new ArrayList();错
- <?>: 支持任意泛型类型
- <? extends A>: 支持A类以及A类的子类,规定了泛型的上限
- <? super A>: 支持A类以及A类的父类,不限于直接父类,规定了泛型的下限
-
JUnit
- 为什么需要JUnit:
- 一个类有很多功能代码需要测试,为了测试,就需要写入到main方法中
- 如果有多个功能代码测试,就需要来回注销,切换很麻烦
- 如果可以直接运行一个方法,就方便很多,并且可以给出相关信息就好了
- 基本介绍:
- JUnit是一个java语言的单元测试框架
- 多数Java的开发环境都已经集成了JUnit作为单元测试的工具
java绘图坐标体系
-
坐标体系-介绍:
- 下图说明了Java坐标系。坐标原点位于左上角,以像素为单位。在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素
-
像素是一个密度单位
绘图原理
- Component类提供了两个和绘图相关最重要的方法:
- paint(Graphics g)绘制组件的外观
- repaint()刷新组件的外观
- 当组件第一次在屏幕显示的时候,程序会自动的调用paint()方法来绘制组件
- 在以下情况paint()将会被调用:
- 窗口最小化,再最大化
- 窗口的大小发生变化
- repaint方法被调用
- Graphics类: 可以理解为画笔
- 画图片先要获取图片资源
Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource());
-
事件处理机制:
- java事件处理是采取"委派事件模型"。当事件发生时,产生事件的对象,会把此"信息"传递给"事件的监听者"处理,这里所说的"信息"实际上就是java.awt.event事件类库里某个类所创建的对象,把它称为"事件的对象"。
-
事件处理机制深入理解:
-
事件源:事件源是一个产生事件的对象,比如按钮,窗体等
-
事件: 事件就是承载事件源状态改变时的对象,比如当键盘事件,鼠标事件,窗口事件等等,会生成一个事件对象,该对象保存着当前事件很多信息,比如KeyEvent对象有含有被按下键的Code值。
-
事件监听器接口:
- 当事件源产生一个事件,可以传送给事件监听者处理
- 事件监听者实际上就是一个类,该类实现了某个事件监听器接口
- 事件监听器接口有多种,不同的事件监听器接口可以监听不同的事件,一个类可以实现多个监听接口
- 这些接口在java.awt.event包和javax.swing.event包中定义。
-
线程
-
相关概念:
- 程序: 是为完成特定任务,用某种语言编写的一组指令的集合。简单的说:就是我们写的代码
- 进程:
- 是指运行中的程序,比如我们使用QQ就启动了一个进程,操作系统就会为该进程分配内存空间
- 进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有它自身的产生,存在和消亡的过程
- 线程:
- 线程由进程创建的,是进程的一个实体
- 一个进程可以拥有多个线程
- 单线程:同一时刻,只允许执行一个线程
- 多线程:同一个时刻,可以执行多个线程
- 并发:同一个时刻,多个任务交替执行,造成一种"貌似同时"的错觉,简单的说,单核cpu实现的多任务就是并发
- 并行:同一时刻,多个任务同时执行,多核cpu可以实现并行
-
创建线程的两种方法:
- 继承Thread类,重写run方法
- 实现Runnable接口,重写run方法
- 使用JConsole监控线程执行情况
-
继承Thread VS 实现Runnable的区别
- 从java的设计来看,通过继承Thread或者实现Runnable接口创建线程本质上没有区别,从jdk帮助文档我们可以看到Thread类本身就实现了Runnable接口
- 实现Runnable接口方式更加适合多个线程共享一个资源的情况,并且避免了单继承的限制
-
线程终止:
- 当线程完成任务后,会自动退出
- 还可以通过使用变量来控制run方法退出的方式停止线程,即通知方式
-
线程常用方法(1):
- setName //设置线程名称,使之与参数name相同
- getName //返回该线程的名称
- start //使该线程开始执行;Java虚拟机底层调用该线程的start0方法
- run //调用线程对象run方法
- setPriority //更改线程的优先级
- getPriority //获取线程的优先级
- sleep //在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
- interrupt //中断线程
-
注意事项和细节:
- start底层会创建新的线程,调用run,run就是一个简单的方法调用,不会启动新线程
- 线程优先级的范围
- interrupt,中断线程,但并没有真正的结束线程。所以一般用于中断正在休眠线程
- sleep:线程的静态方法,使当前线程休眠
-
线程常用方法(2):
- yield: 线程的礼让。让出cpu,让其它线程执行,但礼让的时间不确定,所以不一定礼让成功
- join:线程的插队。插队的线程一旦插队成功,则肯定先执行完插入的线程所有的任务
-
用户线程和守护线程
- 用户线程:也叫工作线程,当线程的任务执行完或通知方式结束
- 守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束
- 常见的守护线程:垃圾回收机制
-
线程7大状态:
-
线程的同步
-
在多线程编程,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何同一时刻,最多有一个线程访问,以保证数据的完整性。
-
也可以这里理解:线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其它线程才能对该内存地址进行操作。
-
具体方法:
-
同步代码块:
synchronized(对象) {//得到对象的锁,才能操作同步代码
//需要被同步代码;
}
-
synchronized还可以放在方法声明中,表示整个方法-为同步方法
public synchronized void m(String name){
//需要被同步的代码
}
-
-
互斥锁
- 基本介绍:
- Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性
- 每个对象都对应于一个可称为"互斥锁"的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
- 关键字synchronized来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问
- 同步的局限性: 导致程序的执行效率要降低
- 同步方法(非静态的)的所可以是this,也可以是其它对象(要求时同一个对象)
- 同步方法(静态的)的锁为当前类本身
- 注意事项和细节:
- 同步方法如果没有使用static修饰:默认锁对象为this
- 如果方法使用static修饰,默认锁对象: 当前类.class
- 实现的落地步骤:
- 需要先分析上锁的代码
- 选择同步代码块或同步方法
- 要求多个线程的锁对象为同一个
- 死锁:
- 多个线程都占用了对方的锁资源,但不肯相让,导致了死锁
释放锁
- 下面操作会释放锁:
- 当前线程的同步方法,同步代码块执行结束
- 当前线程在同步代码块,同步方法中遇到break,return
- 当前线程在同步代码块,同步方法中出现了未处理的Error或Exception,导致异常结束
- 当前线程在同步代码块,同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁
- 下面操作不会释放锁:
- 线程执行同步代码块或同步方法时,程序调用Thread.sleep(),Thread.yield()方法暂停当前线程的执行,不会释放锁
- 线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁