1.Overload和Override的区别。Overloaded的方法是否可以改变返回值类型。
解释:重写Override和重载Overload是Java多态性的不同表现。重载Overload函数里面可以有相同的函数名但参数名、返回值、类型不能相同;或者说可以改变参数、类型、返回值但函数名字依然不变。重写Override子类继承父类的时候子类中可以定义某方法与其父类有相同的名称和参数,当子类调用这一函数时自动调用子类的方法,而父类相当于被覆盖(重写)了。
重写Override特点:1、覆盖方法的标志必须要和被覆盖方法的标志完全匹配,才能达到覆盖效果。2、覆盖的方法的返回值必须和被覆盖方法的返回值一致。3、覆盖方法所抛出的异常必须和被覆盖方法所抛出的异常一致,或者是其子类。4、被final修饰的方法不能被重写。5、对于继承来说,如果某一方法在父类中访问权限是private,那么子类就不能对其进行重写覆盖。 重载Overload特点:1、在使用重载时只能通过不同的参数样式。比如不同的参数类型,不同的参数个数,不同的参数顺序。2、不能通过访问权限,返回类型,抛出的异常进行重载。3、方法的异常类型和数目不会对重载造成影响。4、重载事件通常发生在同一个类中,不同方法之间的现象。5、存在于同一类中,只有虚方法和抽象方法才能被重写。 重写Override实现机制 :重写是一种动态绑定的多态机制。即在父类和子类中同名元素有不同的实现代码。执行的是那个代码是根据运行时实际情况而定的。 重载Overload实现机制:重载是一种参数多态机制。即代码通过参数的类型或者个数不同而实现的多态机制。是一种静态的绑定机制。在编译是已经知道具体执行的是哪个代码段。
2.String、StringBuffer和StringBuilder的区别
1、三者在执行速度上:StringBuilder>StringBuffer>String(由于String被final修饰的,是常量,不可改变,拼接时会重新创建新的对象)。2、StringBuffer是线程安全的,StringBuilder是线程不安全的。
性能比较:String:它在拼接字符串的时候,每拼接一个就会创建一个StringBuilder,从而通过Stringbuilder的append()方法拼接,然后返回一个新的String的对象,然后再继续拼接下一个字符串变量,这样就会导致重复创建StringBuilder对象,比较耗内存,性能低下,这是在用加号+的情况下。如果用concat()拼接字符串时,则每两个字符串拼接都会创建一个char[]进行内容拼接并返回一个新的String对象作为结果,重复调用concat()会导致重复创建char[]和新的String对象,性能低下,耗内存。
StringBuilder在调用toString()之前都不会创建拼接结果,并且底层的char数组会自动扩容,一直到需要拼接的字符串全部存入char数组后,调用toString()才创建新的String对象并返回,这样就避免了重复创建,效率提高。
StringBuffer因为使用了syncrhoized对append()进行了加锁,所导致性能稍微低于StringBuilder。
使用场景:拼接两个字符串变量,用String;单线程下拼接两个字符串变量,用StringBuilder;多线程下拼接两个字符串变量,用Stringbuffer。
3.final、finally、finalize的区别
final修饰符:被final修饰的类,就意味着不能再派生出新的子类,不能作为父类被子类继承,因此一个类不能既被abstract声明,又被final声明。将变量或方法声明为final,可以保证他们在使用的过程中不被修改。被声明为final的变量必须在声明时给出变量的初始值,而在以后的引用中只能读取。被final声明的方法也同样之只能使用,不能被重写。
finally是在异常处理时提供finally块来执行任何清除操作,不管有没有异常被抛出、捕获、finally块都会被执行。try块中的内容是在无异常时执行到结束。catch块中的内容是在try块内容发生catch所声明的异常时,跳转到catch块中执行。finally块则是无论异常是否发生,都会执行finally块的内容,所以在代码逻辑中有需要无论发生什么都必须执行的代码,就可以放在finally块中。
finalize是方法名,Java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的,它是在object类中定义的,因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理操作。finalize()方法是在垃圾收集器删除对象之前对这个对象调用的。
4.sleep()和wait()区别
sleep()方法是Thread类的静态方法,wait()是Object类的成员方法。sleep()方法导致程序暂停执行指定的时间,让出cpu给其他的线程,但是他的监控状态依然保持着,当知道指定时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。wait()方法会放弃对象锁,进入等待此对象的等待锁定池中,只有针对此对象调用notify()/notifyAll()方法后本线程才会进入对象锁定池中准备。sleep()方法需要抛异常,而wait()方法不需要。sleep()方法可以在任何地方使用,wait()方法只能在同步方法和同步代码块中使用。
sleep()方法表示让一个线程进入睡眠状态。等待一定时间后,自动醒来进入可运行状态,不会马上进入运行状态,因为线程调度机制不会恢复线程的运行也需要时间,一个线程对象调用了sleep()方法后并不会释放它所持有的所有的对象锁,所以也就不会影响其他进程对象的运行。但在sleep()的过程中有可能被其他对象调用它的interrupt(),产生interruptedException()异常,如果你的程序不捕获这个异常,线程就会异常终止,进入TERMINATED状态,如果你的程序捕获了这个异常,那么程序就会继续执行catch语句块可能还有finally语句块。
注意sleep()方法是一个静态的方法,它只对当前对象有效也就是说只会使当前线程被sleep()。
wait()一旦对象调用了wait()方法,必须采用notify()或者notifyAll()方法唤醒该线程;如果县城拥有某个或某些对象的同步锁,那么再调用了wait()后,这个线程就会释放它持有的所有同步资源,而不限于这个被调用了wait()方法的对象。wait()方法也同样会在wait()的过程中有可能被其他对象调用interrupt()方法。
如果线程A希望立即结束线程B,则可以对线程B的实例调用interrupt()方法,如果线程B正在wait/sleep/join,则线程B会立刻抛出interruptedException,在catch()方法中直接return即可安全的结束线程。但是如果线程B正在执行逻辑代码,则线程B不会立刻抛出此异常。
waite()和notify()因为会对对象的锁标志进行操作,所以他们必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,可以编译通过,但在运行时会发生illegalMonitorStateException的异常。
5.抽象类和接口的区别
一个类只能继承单个类,但可以实现多个接口,接口强调特定功能的实现,而抽象类强调所属关系,抽象类中的所有的方法并不一定时抽象的,比如可以在抽象类中实现一些基本方法,接口要求所有的方法必须是抽象的
接口中可以包含变量和方法,需要注意的是接口中的变量会被隐式的指定为public static final变量,不能改变,用其他修饰符修饰会编译错误,并且接口中所有的方法不能有具体的实现,也就是说接口中的方法必须都是抽象方法,也可以理解为方法默认的都是抽象方法,如果一个非抽象的类实现了某个接口,就必须实现接口中的所有方法,如果一个抽象类实现了某个接口,可以不实现该接口中的抽象方法。
总结:抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract方法;抽象类中的成员变量可以是各种类型,而接口中的成员变量只能是public static final类型的;接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;一个类只能继承一个抽象类,而一个类可以实现多个接口。