1、熟悉封装、继承、多态、重载、重写等概念,并以实例进行说明
封装
封装就是将对象的属性和实现细节隐藏起来,并提供公共访问方式。
封装的好处:隐藏类的实现细节,让使用者只能通过程序员规定的方法来访问数据,可以方便的加入存取控制语句,限制不合理操作。
实例:
public class Dog {
//私有化属性
private String name;
private String sex;
private String color;
//封装字段
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getSex() {
return sex;
}
public void setColor(String color) {
this.color = color;
}
public String getColor() {
return color;
}
}
继承
继承主要要用到这几个关键字:
1.extends关键字: 使用extends关键字,子类就拥有了父类的所有属性和方法(拥有不代表就能访问).
2.super关键字: 父类对象的引用,例如:super.name 就是调用父类的name 属性;super(name)表示调用父类的构造方法,传入那么参数,
继承需要注意的问题:
只允许单一继承,任何一个类,只有一个直接继承的父类.
继承层次太多的时候,代码也会显得非常混乱,最好控制继承的层次<=3;
final会显示禁止某个类被继承,表示最后一个类,不可被继承或者修改.。
多态
多态一个引用可能表现出多种形态,一个父类引用可以对应到不同的子类对象,不同子类对象具体的行为都会存在差异.
//创建子类
public class Shape {
public void draw() {
// 绘制
// 对于 Shape 来说暂时啥都不画
}
}
子类重写父类方法:
public class Circle extends Shape {
@Override
public void draw() {
System.out.println("○");
}
}
public class Rect extends Shape {
@Override
public void draw() {
System.out.println("□");
}
}
public class Flower extends Shape {
@Override
public void draw() {
System.out.println("♣");
}
}
public class Test {
public static void main(String[] args) {
Shape shape=new circle();//向上转型
shape.draw();
shape=new Rect();
shape.draw();
shape=new Flower();
shape.draw()
}
结果:
方法重载(overload)
描述两个普通方法之间,名字相同,参数不同,和继承没有直接关系,和返回值无关;
方法重写(override)
必须是父类方法和子类方法之间,名字相同,参数也相同,和返回值无关,一般情况下在重写方法的时候尽量不要修改返回值的类型.
2、熟悉异常处理机制
java使用面向对象的方式来处理异常,它把程序中发生的每个异常分别封装到一个对象中,该对象包含有异常的信息.所有异常的根类是Throwable,Throwable又派生了两个子类,Error和Exception
Exception包括运行时期异常和编译期异常
运行时期异常的特点:
①方法定义中无需throws声明,调用者也无需try-catch处理此异常.
②运行时期异常一旦发生,需要程序人员修改源代码.(这些异常通常是由于逻辑错误引起的)
一般异常(编译时异常):
必须进行处理的异常,如果不处理,程序就不能编译通过,可以通过try…catch处理或用throws声明继续抛给上层调用方法处理
error:
Error错误通常没有具体的处理方式,程序将会结束运行。Error错误的发生往往都是系统级别的问题,都是jvm所在系统发生的,并反馈给jvm的。我们无法针对处理,只能修正代码。
常见的运行时异常有:
NullPointerException
ClassCastException
ArrayIndexOutOfBoundsException
ArithmeticException
IllegalArgumentException
IllegalStateException
异常处理时需要注意的问题:
①java异常处理用到了多态的概念,如果在异常处理过程中,先捕获了基类,然后在捕获子类,那么捕获子类的代码块永远不会执行.因此,在进行异常捕获时,正确的写法是先捕获子类,再捕获父类的异常信息
正确的写法
try{
}catch( SQLException e){
}catch(Exception){
}
②异常能处理就处理,不能处理就抛出.对于一般异常,如果不能进行行之有效的处理,最好转换成运行时异常抛出
3、熟悉多线程
一、线程的生命周期:
新建 :从新建一个线程对象到程序start() 这个线程之间的状态,都是新建状态;
就绪 :线程对象调用start()方法后,就处于就绪状态,等到JVM里的线程调度器的调度;
运行 :就绪状态下的线程在获取CPU资源后就可以执行run(),此时的线程便处于运行状态,运行状态的线程可变为就绪、阻塞及死亡三种状态。
等待/阻塞/睡眠 :在一个线程执行了sleep(睡眠)、suspend(挂起)等方法后会失去所占有的资源,从而进入阻塞状态,在睡眠结束后可重新进入就绪状态。
终止 :run()方法完成后或发生其他终止条件时就会切换到终止状态。
二、java多线程的几种实现方式:
1.继承Thread类,重写run方法
2.实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target
3.通过Callable和FutureTask创建线程
4.通过线程池创建线程 (上一篇已经讲过了)
前面两种可以归结为一类:无返回值,原因很简单,通过重写run方法,run方式的返回值是void,所以没有办法返回结果
后面两种可以归结成一类:有返回值,通过Callable接口,就要实现call方法,这个方法的返回值是Object,所以返回的结果可以放在Object对象中
三、常用方法
Thread.yield():当前线程可转让cpu控制权,让别的就绪状态线程运行(切换)
Thread.sleep():使线程暂停执行一段时间的方法。
Thread.await():它也是一种使线程暂停执行的方法。
Thread.yield():该方法和sleep方法类似,也是Thread类提供的一个静态方法,可以让正在执行的线程暂停,但是不会进入阻塞状态,而是直接进入就绪状态。
join():在一个线程中调用other.join(),将等待other执行完后才继续本线程。
interrupte():中断线程
具体来说sleep()方法和await()方法的区别主要表现在以下几个方面?
1、原理不同
sleep()方法是Thread类的静态方法,是线程用来控制自身流程的,它会使线程暂停执行一段时间,而把执行机会让给其他线程,等到计时时间一到,此线程会自动被唤醒。
例如:当线程执行报时功能时,每一秒钟打印出一个时间,那么此时就需要在打印方法前面加上一个sleep()方法,以便让自己每隔1s执行一次。
wait()方法是Object类的方法,用于线程间通信,这个方法会使当前拥有该对象锁的线程等待,直到其他线程调用notify()方法或者notifyAll()方法才会被唤醒,不过也可以给线程指定时间被唤醒。
2、对锁的处理机制不同
由于sleep()方法的主要作用是让线程暂停执行一段时间,时间一到则自动恢复,不涉及线程间通信,因此调用sleep()方法并不会释放锁。
wait方法则不同,当调用wait()方法后,线程会释放掉它锁占用的锁,从而使线程所在对象中的其他synchronized数据可被别的线程使用。
3、使用区域不同
由于wait()方法的特殊意义,因此它必须放在同步控制方法或者同步语句块中使用,而sleep()方法则可以放在任何地方使用
sleep()方法必须捕获异常,而wait()、notify()、notifyall()不需要捕获异常。在sleep的过程中,有可能被其他对象调用它的interrupt()、产生interruptedException异常。
由于sleep不会释放"锁标志",容易导致死锁问题的发生
sleep()和yield()方法有什么区别?
1、sleep()方法在给其他线程运行机会时不考虑线程的优先级。因此会给低优先级的线程运行的机会,而yield()方法只会给相同优先级或更高优先级的线程运行的机会。
2、 线程执行sleep()方法后会转入阻塞状态,所以执行sleep()方法的线程在指定的时间内肯定不会被执行,而yield()方法只是使当前线程重新回到就绪状态,所以执行yield()方法的线程有可能在进入到就绪状态后又立马被执行。
四、线程同步与锁。
同步方法1:
同步函数:就是用synchronize关键字修饰的方法。因为每个java对象都有一个内置锁,当用synchronize关键字修饰方法时内置锁会保护整个方法,而在调用该方法之前,要先获得内置锁,否则就会处于阻塞状态。
同步方法2:
同步代码块:就是拥有synchronize关键字修饰的语句块,被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。
五、死锁
进程A中包含资源A,进程B中包含资源B,A的下一步需要资源B,B的下一步需要资源A,所以它们就互相等待对方占有的资源释放,所以也就产生了一个循环等待死锁。
死锁形成的必要条件总结(都满足之后就会产生):
①、互斥条件:资源不能被共享,只能被同一个进程使用;
②、请求与保持条件:已经得到资源的进程可以申请新的资源;
③、非剥夺条件:已经分配的资源不能从相应的进程中强制剥夺;
④、循环等待条件:系统中若干进程形成环路,该环路中每个进程都在等待相邻进程占用的资源。