1. Override 和 Overload 的含义去区别
- Override(重写)
重写(Overriding)是父类与子类之间多态性的一种表现。
覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
覆盖的方法的返回值必须和被覆盖的方法的返回一致;
覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
方法被定义为final不能被重写。
对于继承来说,如果某一方法在父类中是访问权限是private,那么就不能在子类对其进行重写覆盖,如果定义的话,也只是定义了一个新方法,而不会达到重写覆盖的效果。
- Overload(重载)
重载(Overloading)是一个类中多态性的一种表现。
在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int, float), 但是不能为fun(int, int));
不能通过访问权限、返回类型、抛出的异常进行重载;
方法的异常类型和数目不会对重载造成影响;
重载事件通常发生在同一个类中,不同方法之间的现象。
存在于同一类中,但是只有虚方法和抽象方法才能被覆写。
2. Interface 与 abstract 类的区别
接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。
下面比较一下两者的语法区别:
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4.抽象类中的抽象方法的访问类型可以是public,protected,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5.抽象类中可以包含静态方法,接口中不能包含静态方法
6.抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
7.一个类可以实现多个接口,但只能继承一个抽象类。
3. static class 与 non static class 的区别
static class | non static class |
---|---|
内部静态类不需要有指向外部类的引用 | 非静态内部类需要持有对外部类的引用 |
静态类只能访问外部类的静态成员,不能访问外部类的非静态成员 | 非静态内部类能够访问外部类的静态和非静态成员 |
- | 一个非静态内部类不能脱离外部类实体被创建 |
- | 一个非静态内部类可以访问外部类的数据和方法 |
4. Java 多态的实现原理
子类Child继承父类Father,我们可以编写一个指向子类的父类类型引用,该引用既可以处理父类Father对象,也可以处理子类Child对象。
当相同的消息发送给子类或者父类对象时,该对象就会根据自己所属的引用而执行不同的行为,这就是多态。
即多态性就是相同的消息使得不同的类做出不同的响应。
5. 实现多线程的两种方法:Thread 与 Runable
- 继承 Thread 类
1.定义类继承Thread;
2.覆写Threa类的run方法。 自定义代码放在run方法中,让线程运行;
3.调用线程的star方法。
- 实现 Runable 接口
1.定义类实现 Runnable 接口;
2.覆盖 Runnable 接口中的 run 方法,运行的代码放入run方法中;
3.通过 Thread 类建立线程对象;
4.将 Runnable 接口的子类对象作为实际参数传递给 Thread 类的构造函数;
因为,自定义的 run 方法所属的对象是 Runnable 接口的子类对象。所以要让线程去执行指定对象的 run 方法。就必须明确该 run 方法所属对象;
5.调用 Thread 类的 start 方法开启线程并调用 Runnable 接口子类的 run 方法。
6. 线程同步的方法:sychronized、lock、reentrantLock 等
- sychronized
Java 中最基本同步互斥的手段,可以修饰代码块、方法、类;
在修饰代码块的时候需要一个 reference 对象作为锁的对象;
在修饰方法的时候默认是当前对象作为锁的对象;
在修饰类时候默认是当前类的 Class 对象作为锁的对象。
synchronized 会在进入同步块的前后分别形成 monitorenter 和 monitorexit 字节码指令;
在执行 monitorenter 指令时会尝试获取对象的锁,如果此对象没有被锁或者已经被当前线程锁住,那么锁的计数器加一;
每当 monitorexit 被锁的对象的计数器减一,直到为 0 就释放该对象的锁。
由此 synchronized 是可重入的,不会出现自己把自己锁死。
可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响
- lock
lock 是一个类,通过这个类可以实现同步访问;
必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象;
- reentrantLock
对象的方式来操作对象锁.相对于 sychronized 需要在 finally 中去释放锁;
1.等待可中断。在持有锁的线程长时间不释放锁的时候,等待的线程可以选择放弃等待。tryLock(long timeout, TimeUnit unit);
2.公平锁。按照申请锁的顺序来一次获得锁称为公平锁。synchronized 的是非公平锁,ReentrantLock 可以通过构造函数实现公平锁。new RenentrantLock(boolean fair);
3.绑定多个 Condition。通过多次 new Condition 可以获得多个 Condition 对象,可以简单的实现比较复杂的线程同步的功能。通过 await()、signal()。
7. 锁的等级:方法锁、对象锁、类锁
在修饰代码块的时候需要一个 reference 对象作为锁的对象;
在修饰方法的时候默认是当前对象作为锁的对象;
在修饰类时候默认是当前类的 Class 对象作为锁的对象。
8. 写出生产者消费者模式
准确说应该是“生产者-消费者-仓储”模型,离开了仓储,生产者消费者模型就显得没有说服力了。
对于此模型,应该明确一下几点:
1.生产者仅仅在仓储未满时候生产,仓满则停止生产;
2.消费者仅仅在仓储有产品时候才能消费,仓空则等待;
3.当消费者发现仓储没产品可消费时候会通知生产者生产;
4.生产者在生产出可消费产品时候,应该通知等待的消费者去消费。
https://www.cnblogs.com/linjiqin/p/3217050.html
https://www.cnblogs.com/chentingk/p/6497107.html