1. 作用域public,private,protected,以及不写时的区别?
作用域与可见性 | 当前类 | 同一package | (同包和不同包)子类 | 其他package |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
当前类private---同一个包default-----子类protected-----其他包public 主要是作用域不同!
2,说说String、StringBuilder、StringBuffer区别?
- String 字符串常量、StringBuffer 字符串变量(线程安全)、StringBuilder 字符串变量(非线程安全)
他们三者的区别,总的来说就是String是不可变的,是一个字符串常量,而StringBuffer和StringBuilder都是一个变量,对于StringBuffer则是线程安全的,而StringBuilder则是非线程安全的,其他的两者几乎一样。根据这三者的区别用法如下:
当操作数据量较小可采用String
数据量比较大且需要修改字符串的话最好使用StringBuffer或者StringBuilder
在单线程中使用StringBuilder
在多线程中使用StringBuffer
总的来说StringBuffer线程安全但是效率低,而StringBilder非线程安全但是效率高
3,关于overload(重载)和override(重写)
4,线程相关?调度线程使其运行的是.start(),run()
Java的线程是通过java.lang.Thread类来实现的。JVM启动时会有一个由主方法所定义的线程。可以通过创建Thread的实例来创建新的线程。每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。通过调用Thread类的start()方法来启动一个线程。线程有5状态
- 创建状态new Thread()。生成线程对象,并未调用该对象的start方法时候。
- 就绪状态start()。1:调用了线程对象的start方法之后,调度程序未把该线程设置为当前线程。2:在线程运行之后,从等待或者睡眠中回来之后。
- 运行状态run()。线程调度程序把就绪状态的线程设置为当前线程,进入运行状态。
- 阻塞状态blocker()。线程正在运行的时候,被暂停,通常是为了等待某个事件的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
- 死亡状态stop()。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。已经死亡的线程,无法再用start方法进入就绪状态。
5,面向对象的特征有哪些方面
主要有以下四方面:(貌似也可以答3个方面)
1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。
2. 封装:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
3. 继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派生,这个过程称为类继承。新类继承了原始类的特性,叫派生类(子类),而原始叫基类(父类)。子可以在父继承方法和实例变量,还可以修改或增加新的方法。
4. 多态:多态性是指允许不同类的对象对同一消息作出响应。多态灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
6,谈谈final, finally, finalize的区别
final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,不能重载
finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,然后控制就会进入 finally 块(如果有的话)
finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的
7,创建线程的方式及实现?
继承 Thread 类创建线程;
A)定义 Thread 类的子类,并重写该类的 run() 方法,该 run() 方法的方法体就代表了线程要完成的任务,因此把 run() 方法称为执行体;B)创建 Thread 子类的实例,即创建了线程对象; C)调用线程对象的 start() 方法来启动该线程。
实现 Runnable 接口创建线程;
A)定义 runnable 接口的实现类,并重写该接口的 run() 方法,该 run() 方法的方法体同样是该线程的线程执行体;
B)创建 Runnable 接口实现类的实例,并依此实例作为 Thread 的 target 来创建 Thread 对象,该 Thread 对象才是真正的线程对象;
C)调用线程对象的 start() 方法来启动该线程。
使用 Callable 和 Future 创建线程。
A)创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值;
B)创建 Callable 实现类的实例,使用 Future Task 类来包装 Callable 对象,该 Future Task 对象封装了该 Callable 对象的 call() 方法的返回值;
C)使用 Future Task 对象作为 Thread 对象的 target 创建并启动新线程;
D)调用 Future Task 对象的 get() 方法来获得子线程执行结束后的返回值。
三种方式的比较:
1> 通过 Runnable 和 Callable 创建多线程:
优势:
A)线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类;
B)在这种方式下,多个线程可以共享同一个 target 对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将 CPU、代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
劣势:
C)编程稍微复杂,如果要访问当前线程,必须使用 Thread.currentThread() 方法。
D) Runnable 和 Callable 的区别:
重写的方法是 run() 重写的方法是call()
Runnable的任务是不能返回值的 Callable的任务执行后可返回值
run()方法不可以抛出异常 call() 方法可以抛出异常
运行 Callable 任务可以看到一个 Future 对象,表示异步计算的结果。
使用继承 Thread 类的方式创建多线程:
优势:
如果要访问当前线程,则无需使用 Thread.currentThread() 方法,使用 this即可;
劣势:
已经继承了 Thread 类,不能再继承其他父类。
8,不通过构造函数也能创建对象么?答案:对!
(1) 用new语句创建对象,这是最常见的创建对象的方法。-----显式的调用构造函数
(2) 运用反射手段,调用java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。------显式的调用构造函数
(3) 调用对象的clone()方法。内存上对已有对象的克隆,不会调用构造函数
(4) 运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。从文件中还原类的对象,不会调用构造函数。
9,接口和抽象类的区别?
一个类只能继承一个类(抽象类),但是可以实现多个接口
第一点. 接口是抽象类的变体,接口中所有的方法都是抽象的。而抽象类是声明方法的存在而不去实现它的类。
第二点. 接口可以多继承,抽象类不行
第三点. 接口定义方法,不能实现,而抽象类可以实现部分方法。
第四点. 接口中基本数据类型为static 而抽类象不是的。
当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。
抽象类的功能要远超过接口,但是,定义抽象类的代价高。因为高级语言来说(从实际设计上来说也是)每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的
所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度的。