1、面向对象的特征有哪些方面?
答:面向对象的特征主要有以下几个方面:
-- 抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关具体细节是什么。
-- 封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口(可以想想普通洗衣机和全自动洗衣机的差别,明显全自动洗衣机封装更好因此操作起来更简单;我们现在使用的智能手机也是封装得足够好的,因为几个按键就搞定了所有的事情)。
-- 继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。
-- 多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。
2、访问修饰符public,private,protected,以及不写(默认)时的区别?
答:类的成员不写访问修饰时默认为default。范围见下图:
修饰符 | 当前类 | 同 包 | 子 类 | 其他包 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
3、String 是最基本的数据类型吗?
答:不是。Java中的基本数据类型只有8个:byte、short、int、long、float、double、char、boolean。
4、int和Integer有什么区别?
答:Java是一个近乎纯洁的面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。
Java 为每个原始类型提供了包装类型:
-
原始类型: boolean,char,byte,short,int,long,float,double
-
包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
5、重载(Overload)和重写(Override)的区别?
答:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问(只能比父类访问范围更大),不能比父类被重写方法声明更多的异常(里氏代换原则)。
6、抽象类(abstract class)和接口(interface)有什么异同?
答:抽象类和接口都不能够实例化(new XXX),但可以定义抽象类和接口类型的引用(XXX xx = new XXX的实现类)。一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类。接口比抽象类更加抽象,因为抽象类中可以定义构造器,可以有抽象方法和具体方法,而接口中不能定义构造器而且其中的方法全部都是抽象方法。抽象类中的成员可以是private、default、protected、public的,而接口中的成员全都是public的。抽象类中可以定义成员变量,而接口中定义的成员变量实际上都是常量。有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法。
7、Java里的传引用和传值的区别是什么?
答:传引用是指传递的是地址而不是值本身,传值则是传递值的一份拷贝。
8、==与equals的区别?
答:==比较的是引用而equals方法比较的是内容。public boolean equals(Object obj) 这个方法是由Object对象提供的,可以由子类进行重写。
9、如何将String类型转化成Number类型?
答:Integer类的valueOf方法可以将String转成Number。
10、&操作符和&&操作符有什么区别?
答:&是位运算符,表示按位与运算;&&是逻辑运算符,表示逻辑与(and)。除了长得像没有半点关系。
11、switch 语句能否作用在byte 上,能否作用在long 上,能否作用在String上?
答:在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量(更大字体),整数表达式可以是int基本类型或Integer包装类型,由于,byte,short,char都可以隐含转换为int,所以,这些类型以及这些类型的包装类型也是可以的。显然,long和String类型都不符合switch的语法规定,并且不能被隐式转换成int类型,所以,它们不能作用于swtich语句中。
12、short s1 = 1; s1 = s1 + 1; 有什么错? short s1 = 1; s1 +=1; 有什么错?
答:对于
short s1 = 1;
s1 = s1 + 1;
由于s1+1运算时会自动提升表达式的类型,所以结果是int型,再赋值给short类型s1时,编译器将报告需要强制转换类型的错误。
对于
short s1 = 1;
s1 += 1;
由于 +=是java语言规定的运算符,java编译器会对它进行特殊处理,因此可以正确编译。
13、使用final 关键字修饰一个变量时,是引用不能变,还是引用的对象不能变?
答:使用final关键字修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内容还是可以改变的。例如,对于如下语句:
final StringBuffer a=new StringBuffer("abcdefg");
执行如下语句将报告编译期错误:
a=new StringBuffer("");
但是,执行如下语句则可以通过编译:
a.append("xxoo");
14、String s = new String("xyz"); 创建了几个String Object?
答:两个或一个,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,它一句那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。
15、StringBuffer 与StringBuilder的区别?
答:StringBuilder不是线程安全的,运行效率高;StringBuffer是线程安全的,运行效率不及StringBuilder。
16、数组有没有length() 这个方法?String 有没有length() 这个方法?
答:数组没有length()这个方法,有length的属性。String有有length()这个方法。
17、final, finally, finalize的区别?
答:final用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收。
18、启动一个线程是用run() 还是start()?
答:启动一个线程是调用start()方法,使线程就绪状态,以后可以被调度为运行状态,一个线程必须关联一些具体的执行代码,run()方法是该线程所关联执行的代码。
19、字节流与字符流的区别?
答:在应用中,经常要完全是字符的一段文本输出去或读进来,用字节流可以吗?计算机中的一切最终都是二进制的字节形式存在。对于“中国”这些字符,首先要得到其对应的字节,然后将字节写入到输出流。读取时,首先读到的是字节,可是我们要把它显示为字符,我们需要将字节转换成字符。由于这样的需求很广泛,人家专门提供了字符流的包装类。底层设备永远只接受字节数据,有时候要写字符串到底层设备,需要将字符串转成字节再进行写入。字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再写入底层设备,这为我们向IO设别写入或读取字符串提供了一点点方便。字符向字节转换时,要注意编码的问题,因为字符串转成字节数组,其实是转成该字符的某种编码的字节形式,读取也是反之的道理。
20、什么是java 序列化,如何实现java 序列化?
答:我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,要将java对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个java对象变成某个格式的字节流再传输,但是,jre本身就提供了这种支持,我们可以调用OutputStream的writeObject方法来做,如果要让java帮我们做,要被传输的对象必须实现serializable接口,这样,javac编译时就会进行特殊处理,编译的类才可以被writeObject方法操作,这就是所谓的序列化。需要被序列化的类必须实现Serializable接口。
27、JDBC 中的PreparedStatement 相比Statement 的好处?
答:PreparedStatement 会缓存指令,所以性能比Statement高。PreparedStatement在预编译的时候过滤了特殊字符串,所以会防止SQL注入。
28、数据库三范式是什么?
答:第一范式(1NF):数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。
第二范式(2NF):数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况),也即所有非关键字段都完全依赖于任意一组候选关键字。
第三范式(3NF):在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指的是如果存在"A → B → C"的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系: 关键字段 → 非关键字段x → 非关键字段y
29、什么是主键?什么是外键?
答:主键是表里的(一个或多个)字段,只用来定义表格里的行;主键里的值总是唯一的。外键是一个用来建立两个表格之间关系的约束。这种关系一般都涉及一个表格里的主键字段与另外一个表(可能是同一表)里的字段。那么这些相连的字段就是外键。
30、什么是数据库事务?事务有哪些特性?简述事务的隔离级别?
答:事务是是一系列的数据库操作,是数据库应用的基本逻辑单位。
事务有原子性、一致性、隔离性、持久性。
-- 原子性。即不可分割性,事务要么全部被执行,要么就全部不被执行。
-- 隔离性。在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事务。
-- 持久性。事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。
事务的隔离级别:读未提交(Read Uncommitted):可以发生脏读、不可重复读和幻读;读提交(Read Committed):不可以发生脏读可以发生不可重复读和幻读;可重复读取(Repeatable Read):不可以发生脏读和不可重复读,可以发生幻读;序列化(Serializable):不可以发生脏读、不可重复读和幻读。
-- 脏读:脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的。
事务一 | 事务二 |
---|
/* Query 1 /
SELECT age FROM users WHERE id = 1;
/ will read 20 /
/ Query 2 /
UPDATE users SET age = 21 WHERE id = 1;
/ No commit here /
/ Query 1 /
SELECT age FROM users WHERE id = 1;
/ will read 21 */
ROLLBACK;
-- 不可重复读:是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。比如事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
事务一 事务二
/* Query 1 */
SELECT * FROM users WHERE id = 1;
/* Query 2 /
UPDATE users SET age = 21 WHERE id = 1;
COMMIT;
/ Query 1 */
SELECT * FROM users WHERE id = 1;
COMMIT;
-- 幻读:幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,比如这种修改涉及到表中的“全部数据行”。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入“一行新数据”。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
事务一 事务二
/* Query 1 */
SELECT * FROM users;
/* Query 2 /
INSERT INTO users VALUES ( 3, 'Bob', 27 );
COMMIT;
/ Query 1 */
SELECT * FROM users;
31、HashMap的实现原理?
答:在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,我们先对键调用hashCode()方法,返回的hashCode用于找到数组中的位置来储存Entry对象。当对象的hashcode相同时,它们在数组中的位置相同,“碰撞”会发生。因为HashMap使用线性链表存储对象,这个Entry会存储在线性链表中。将会调用key的eqauls()方法比较决定是采用覆盖行为(返回 true),还是产生 Entry 链(返回 false),新加入的放在链头,最先加入的放在链尾。
32、HashMap与HashTable的区别?
答:HashMap可以接受null键值和值,而Hashtable则不能。
Hashtable是线程安全的,通过synchronized实现线程同步。而HashMap是非线程安全的,但是速度比Hashtable快。
33、ArrayList与LinkedList的区别?
答:两者都实现的是List接口,不同之处在于:
-- ArrayList是基于动态数组实现的,LinkedList是基于链表的数据结构。
-- get访问List内部任意元素时,ArrayList的性能要比LinkedList性能好。LinkedList中的get方法是要按照顺序从列表的一端开始检查,直到另一端
-- 对于新增和删除操作LinkedList要强于ArrayList,因为ArrayList要移动数据
附加:
LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
List list = Collections.synchronizedList(new LinkedList(…));
34、如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?
答:HashMap默认的负载因子大小为0.75,也就是说,当一个map填满了75%的空间的时候,和其它集合类(如ArrayList等)一样,将会创建原来HashMap大小的两倍的数组,来重新调整map的大小,并将原来的对象放入新的数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置。
35、ConcurrentHashMap和Hashtable的区别?
答:它们都可以用于多线程的环境,但是当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。因为ConcurrentHashMap引入了分割(segmentation),不论它变得多么大,仅仅需要锁定map的某个部分,而其它的线程不需要等到迭代完成才能访问map。简而言之,在迭代的过程中,ConcurrentHashMap仅仅锁定map的某个部分,而Hashtable则会锁定整个map。
36、Collection 和 Collections的区别?
答:Collection是集合类的上级接口,继承与他的接口主要有Set 和List.
Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。
37、简单描述java集合类?
答:java集合类都继承于Collection接口,主要有三种:List、Set和Map。
-- List有子类LinkedList、ArrayList和Vector
ArrayList: 元素单个,效率高,多用于查询 。
Vector: 元素单个,线程安全,多用于查询。
LinkedList: 元素单个,多用于插入和删除
-- Set有子类HashSet、SortedSet和TreeSet
-- Map有子类HashMap、HashTable、LinkedHashMap和WeakHashMap
HashMap: 元素成对,元素可为空。
HashTable: 元素成对,线程安全,元素不可为空。
LinkedHashMap:它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap。
WeakHashMap: 是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被。
38、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
答:分几种情况:
-- 其他方法前是否加了synchronized关键字,如果没加,则能。
-- 如果这个方法内部调用了wait,则可以进入其他synchronized方法。
-- 如果其他个方法都加了synchronized关键字,并且内部没有调用wait,则不能。
39、sleep() 和 wait() 有什么区别?
答:sleep就是当前线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep方法并不会释放锁,即使当前线程使用sleep方法让出了cpu,但其他被同步锁挡住了的线程也无法得到执行。
wait是指在一个已经进入了同步锁的线程内,让自己让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是处于wait状态的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在当前线程中,如果notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁),值得注意的是,notify方法只是随机通知一个wait状态的线程,notifyAll方法可以通知所有wait该锁的线程。
例子:
运行结果:
enter thread1...
thread1 is waiting
enter thread2...
thread2 is waiting
enter thread3...
thread2 notify other thread can release wait status..
thread3 is sleeping ten millisecond...
thread3 is going on...
thread3 is being over!
thread1 is going on...
thread1 is being over!
如果调用的是notify,则结果如上,thread1执行完毕,thread2一直被挂着。
40、Java中的volatile 变量是什么?
答:volatile是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其它线程是透明的。volatile变量可以保证下一个读取操作会在前一个写操作之后发生。
41、 什么是线程安全?Vector是一个线程安全类吗?
答:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。一个线程安全的计数器类的同一个实例对象在被多个线程使用的情况下也不会出现计算失误。很显然你可以将集合类分成两组,线程安全和非线程安全的。Vector 是用同步方法来实现线程安全的, 而和它相似的ArrayList不是线程安全的。
42、什么是ThreadLocal变量?
答:ThreadLocal用于创建线程的本地变量,我们知道一个对象的所有线程会共享它的全局变量,所以这些变量不是线程安全的,我们可以使用同步技术。但是当我们不想使用同步的时候,我们可以选择ThreadLocal变量。每个线程都会拥有他们自己的Thread变量,它们可以使用get()\set()方法去获取他们的默认值或者在线程内部改变他们的值。
43、 Java中interrupted 和 isInterruptedd方法的区别?
答:interrupted() 和 isInterrupted()的主要区别是前者会将中断状态清除而后者不会。Java多线程的中断机制是用内部标识来实现的,调用Thread.interrupt()来中断一个线程就会设置中断标识为true。当中断线程调用静态方法Thread.interrupted()来检查中断状态时,中断状态会被清零。而非静态方法isInterrupted()用来查询其它线程的中断状态且不会改变中断状态标识。简单的说就是任何抛出InterruptedException异常的方法都会将中断状态清零。无论如何,一个线程的中断状态有有可能被其它线程调用中断来改变。
44、什么是线程池? 为什么要使用它?
答:创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。从JDK1.5开始,Java API提供了Executor框架让你可以创建不同的线程池。比如单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合很多生存期短的任务的程序的可扩展线程池)。
45、有三个线程T1,T2,T3,怎么确保它们按顺序执行?
答:在多线程中有多种方法让线程按特定顺序执行,你可以用线程类的join()方法在一个线程中启动另一个线程,另外一个线程完成该线程继续执行。为了确保三个线程的顺序你应该先启动最后一个(T3调用T2,T2调用T1),这样T1就会先完成而T3最后完成。
66、MySQL都有哪些存储引擎,有什么区别?
答:主要存储引擎:MyISAM、InnoDB、MEMORY和MERGE,MySQL5.5以后默认使用InnoDB存储引擎。
-- MyISAM不支持事务、也不支持外键,但其访问速度快,对事务完整性没有要求。
-- InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是比起MyISAM存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。
-- MEMORY存储引擎使用存在内存中的内容来创建表。每个MEMORY表只实际对应一个磁盘文件。MEMORY类型的表访问非常得快,因为它的数据是放在内存中的,并且默认使用HASH索引。但是一旦服务关闭,表中的数据就会丢失掉。
-- MERGE存储引擎是一组MyISAM表的组合,这些MyISAM表必须结构完全相同。MERGE表本身没有数据,对MERGE类型的表进行查询、更新、删除的操作,就是对内部的MyISAM表进行的。
67、说说常见的数据库优化?
答:1>创建索引,建索引的字段应满足以下条件:
-- 字段出现在查询条件中,并且查询条件可以使用索引;
-- 语句执行频率高,一天会有几千次以上;
-- 通过字段条件可筛选的记录集很小;
2>使用分页
3>只返回必要字段以减少数据在网络上传输开销
4>使用BATCH操作,减少交互的次数
5>加大fetch_size,这样可以减少结果数据传输的交互次数及服务器数据准备时间,提高性能。
网友评论