java的new Date的语法是什么?

1.1 java基础和语法部分面试题

1.3 容器相关的面试题

1.4 多线程相关的面试题

1.5 IO流想过的面试题

1.6 异常处理相关的面试题

    Java SE : 标准版 定位于个人计算机的应用开发
    Java EE : 企业版 定位于服务端的应用开发
    Java ME :微型版 ,定位于消费性电子产品的应用开发

现在除了long类型不能用,整形,字符串,枚举都能用

  • 共同点:变量自增1 等价于 i=i+1
  • 不同点:i++ 先赋值后自增, ++i 先自增在赋值

重点是要答出短路机制,即

  • ||(短路或)即前面的为true 则不看后面的
  • while先判断后执行,第一次判断为false,循环体一次都不执行
  • do while先执行 后判断,最少执行1次。
  • 如果while循环第一次判断为true, 则两种循环没有区别。
  • break: 结束当前循环并退出当前循环体。

数组是相同数据类型的集合,需要指定长度,会在内存中会开辟出一个连续的空间,每一个空间存放一个变量,称之为数组元素 。

13. 冒泡排序算法(233_基本每回都有)

// 外层循环,它决定一共走几趟 //内层循环,它决定每趟走一次 //如果后一个大于前一个

14. 类和对象的关系

类是对象的抽象,而对象是类的具体实例,说白了类和对象就是,原件和复印件的关系 。

15. 面向对象和面向过程的区别

编程思路不同: 面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类、属性及其方法,然后通过实例化类、执行方法来完成功能。

封装性:都具有封装性,但是面向过程是封装的是功能,而面向对象封装的是数据和功能。

面向对象具有继承性和多态性,而面向过程没有继承性和多态性,所以面向对象优势是明显。

16.方法的重载和重写

  • 对象内部指代自身的引用,也是解决成员变量和局部变量同名问题
  • 在构造方法中不允许省略,必须是构造方法的第一条语句
  • 而且在静态方法当中不允许出现this关键字,因为没有对象存在
  • 代表对当前对象的直接父类对象的引用
  • 可以调用直接父类的成员变量和成员变量,但是都不能被private所修饰
  • 可以调用直接父类的构造方法,只限于构造方法中使用,但是必须是第一条语句
  • 可以修饰变量、方法、代码块和内部类
  • 由该类创建的所有对象共享同一个static属性
  • 可以对象创建后通过对象名.属性名,也可以在没有创建任何对象之前通过类名.属性名的方式来访问。

注意:static修饰的变量是在方法区中,所以可以直接通过类名.属性名的方式来访问,普通变量是在堆中,在没有创建对象时不可以调用19. final 和 abstract 关键字作用abstract 可以用来修饰类和方法,不能用来修饰属性和构造方法;使用abstract修饰的类是抽象类,需要被继承,使用abstract修饰的方法是抽象方法,需要子类被重写。final 可以用来修饰类、方法和属性,不能修饰构造方法。使用final修饰的类不能被继承,使用final修饰的方法不能被重写,使用final修饰的变量的值不能被修改,所以就成了常量。

20. 你了解Object类的常用方法吗?

  • equals() : 比较对象的地址值是否相等,如果子类重写,则比较对象的内容是否相等;

21. 写出访问修饰符的区别

  • 引用类型,比较的是地址
  • 不能比较没有父子关系的两个对象
  • 系统类一般已经覆盖了equals(),比较的是内容。
  • 父类引用变量指向子类的对象;

24. 基本数据类型和包装类的对应关系

25. 为什么要有包装类

Java基本数据类型不是面向对象,因此存在许多不方便之处,为了解决这个问题,包装类应运而生。

27. 使用递归算法,输出某个目录下所有的文件和子目录列表

Java中的序列化机制能够将一个实例对象(只序列化对象的属性值,而不会去序列化什么所谓的方法。)的状态信息写入到一个字节流中使其可以通过socket进行传输、或者持久化到存储数据库或文件系统中;然后在需要的时候通过字节流中的信息来重构一个相同的对象。一般而言,要使得一个类可以序列化,只需简单实现java.io.Serializable接口即可。

对象的序列化主要有两种用途:

  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;

  2) 在网络上传送对象的字节序列。

29. 不通过构造对象也能创建对象吗?

  • 调用对象的clone()方法,因为是在内存上对已有对象的影印,所以不会调用构造函数;
  • 运用序列化手段,是从文件中还原类的对象,也不会调用构造函数;
  • 如果除数与被除数均不为0.0的话,则取值范围为[0, +∞]。+∞在Java中显示的结果为Infinity。
  • 如果除数与被除数均为0.0的话,则运行结果为NaN(Not a Number的简写),计算错误。

31. 接口与抽象类的区别(笔试必有)

  • 抽象类和接口均包含抽象方法,类必须实现所有的抽象方法,否则是抽象类
  • 抽象类和接口都不能实例化,用来被其他类继承和实现
  • 接口中只能定义全局静态常量,不能定义变量。抽象类中可以定义常量和变量。
  • 接口中所有的方法都是全局抽象方法。抽象类中可以有0个、1个或多个,甚至全部都是抽象方法。
  • 抽象类中可以有构造方法,但不能用来实例化,而在子类实例化是执行完
  • 成属于抽象类的初始化操作。接口中不能定义构造方法

二者的主要区别还是在设计理念上,其决定了某些情况下到底使用抽象类还是接口。

抽象类体现了一种继承关系,目的是复用代码,抽象类中定义了各个子类的相同代码,可以认为父类是一个实现了部分功能的“中间产品”,而子类是“最终产品”。父类和子类之间必须存在“is-a”的关系,即父类和子类在概念本质上应该是相同

接口并不要求实现类和接口在概念本质上一致的,仅仅是实现了接口定义的约定或者能力而已。接口定义了“做什么”,而实现类负责完成“怎么做”,体现了功能(规范)和实现分离的原则。接口和实现之间可以认为是一种“has-a的关系”

32. 反射的概念与作用

通过反射可以使程序代码访问装载到JVM 中的类的内部信息

1) 获取已装载类的属性信息

2) 获取已装载类的方法

3) 获取已装载类的构造方法信息

存在,int的最大值,加1后为负数

34. 接口可否继承接口?抽象类是否可实现接口?抽象类是否可继承实体类 接口可以继承接口,抽象类可以实现接口,抽象类可以继承实体类。35. _Class类的getDeclaredFields()方法与getFields()的区别?

  • getDeclaredFields():可以获取所有本类自己声明的方法, 不能获取继承的方法

36. 在switch和if-else语句之间进行选取,当控制选择的条件不仅仅依赖于一个x时,应该使用switch结构;正确么?

37. 使用final关键字修饰符一个变量时,是引用不能变,还是引用的对象不能变?

final修饰基本类型变量,其值不能改变,但是final修饰引用类型变量,栈内存中的引用不能改变,但是所指向的堆内存中的对象的属性值仍旧可以改变

38. 以下代码的输出结果是?

39. 以下代码的输出结果是?

40. try{}里面有一个return语句,那么紧跟在这个try后的finally, 里面的语句在异常出现后,都会执行么?为什么?

  • 在异常处理时提供 finally 块来执行任何清除操作。
  • 如果有finally的话,则不管是否发生异常,finally语句都会被执行,包 括遇到return语句。

41. 如果有两个类A、B(注意不是接口),你想同时使用这两个类的功能,那么你会如何编写这个C类呢?

因为类A、B不是接口,所以是不可以直接实现的,但可以将A、B类定义成父子类,那么C类就能实现A、B类的功能了。假如A为B的父类,B为C的父类,此时C就能使用A、B的功能。

42. 一个类的构造方法是否可以被重载(overloading),是否可以被子类重写(overrding)?

构造方法可以被重载,但是构造方法不能被重写,子类也不能继承到父类的构造方法

43. 如何将日期类型格式化为

//第二步:将日期Date转换成字符串String

45. 为什么不能根据返回类型来区分重载,为什么?

方法的重载,即使返回值类型不同,也不能改变实现功能相同或类似这一既定事实;同时方法的重载只是要求两同三不同,即在同一个类中,相同的方法名称,参数列表当中的参数类型、个数、顺序不同;跟权限修饰符和返回值类无关

46. 抽象的(abstract)方法是否可同时是静态的(static),是否可同时是本地方法(native),是否可同时被synchronized修饰?

抽象方法需要子类重写,而静态的方法是无法被重写的,因此二者是矛盾的。本地方法是由本地代码(如C代码)实现的方法,而抽象方法是没有实现的,也是矛盾的。synchronized和方法的实现细节有关,抽象方法不涉及实现细节,因此也是相互矛盾的。

47. 静态变量和实例变量的区别?

静态变量是被static修饰符修饰的变量,也称为类变量,它属于类,不属于类的任何一个对象,一个类不管创建多少个对象,静态变量在内存中有且仅有一个拷贝;实例变量必须依存于某一实例,需要先创建对象然后通过对象才能访问到它,静态变量可以实现让多个对象共享内存。

48. 是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?

不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,因此在调用静态方法时可能对象并没有被初始化。

49. 如何实现对象克隆?

2.实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆

50. 一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制?

可以,但一个源文件中最多只能有一个公开类(public class)而且文件名必须和公开类的类名完全保持一致。

可以继承其他类或实现其他接口,在Swing编程中常用此方式来实现事件监听和回调。但是有一点需要注意,它只能继承一个类或一个接口。

52. 内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制?

一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。

如果要访问外部类的局部变量,此时局部变量必须使用final修饰,否则无法访问。

(1)修饰类:表示该类不能被继承;

(2)修饰方法:表示方法不能被重写但是允许重载;

(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量);

(4)修饰对象:对象的引用地址不能变,但是对象的初始化值可以变。

54. 说说数据类型之间的转换: 1)如何将字符串转换为基本数据类型? 2)如何将基本数据类型转换为字符串?

  • 一种方法是将基本数据类型与空字符串(””)连接(+)即可获得其所对应的字符串;另一种方法是调用String 类中的valueOf(…)方法返回相应字符串

55. 如何实现字符串的反转及替换?(这个基本必有!!!)

56. Java反射技术主要实现类有哪些,作用分别是什么?

在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中

1)Class类:代表一个类

2)Field 类:代表类的成员变量(属性)

3)Method类:代表类的成员方法

5)Array类:提供了动态创建数组,以及访问数组的元素的静态方法57. char型变量中能不能存储一个中文汉字?

1.java采用unicode编码,2个字节(16位)来表示一个字符, 无论是汉字还是数字,字母,或其他语言都可以存储。

2.char 在java中是2个字节,所以可以存储中文。

不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允许改变。

2. 字符串如何转换为int类型

3. 写一个方法,实现字符串的反转,如:输入abc,输出cba

它们都可以储存和操作字符串,同时三者都使用final修饰,都属于终结类不能派生子类,操作的相关方法也类似例如获取字符串长度等;

其中String是只读字符串,也就意味着String引用的字符串内容是不能被改变的,而StringBuffer和StringBuilder类表示的字符串对象可以直接进行修改,在修改的同时地址值不会发生改变。StringBuilder是JDK 1.5中引入的,它和StringBuffer的方法完全相同,区别在于它是在单线程环境下使用的,因为它的所有方面都没有被synchronized修饰,因此它的效率也比StringBuffer略高。在此重点说明一下,String、StringBuffer、StringBuilder三者类型不一样,无法使用equals()方法比较其字符串内容是否一样

1)为了效率。若允许被继承,则其高度的 被使用率可能会降低程序的性能。

2)为了安全。JDK中提供的好多核心类比如String,这类的类的内部好多方法的实现都不是java编程语言本身编写的,好多方法都是调用的操作系统本地的API,这就是著名的“本地方法调用”,也只有这样才能做事,这种类是非常底层的, 和操作系统交流频繁的,那么如果这种类可以被继承的话,如果我们再把它的方法重写了,往操作系统内部写入一段具有恶意攻击性质的代码什么的, 这不就成了核心病毒了么?

不希望别人改,这个类就像一个工具一样,类的提供者给我们提供了, 就希望我们直接用就完了,不想让我们随便能改,其实说白了还是安全性, 如果随便能改了,那么java编写的程序肯定就很不稳定,你可以保证自己不乱改, 但是将来一个项目好多人来做,管不了别人,再说有时候万一疏忽了呢?他也不是估计的, 所以这个安全性是很重要的,java和C++相比,优点之一就包括这一点;

两个或一个,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。New String每写一遍,就创建一个新的对象,那个常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,这句代表就不会创建”xyz”自己了,直接从缓冲区拿。

第一条语句打印的结果为false,第二条语句打印的结果为true,这说明javac编译可以对字符串常量直接相加的表达式进行优化,不必要等到运行期去进行加法运算处理,而是在编译时去掉其中的加号,直接将其编译成一个这些常量相连的结果,所以只创建一个String对象。

1.3 容器相关的面试题

1)实现原理相同---底层都使用数组

2)功能相同---实现增删改查等操作的方法相似

3)都是长度可变的数组结构,很多情况下可以互用

2)Vector线程安全,ArrayList重速度轻安全,线程非安全

两者都实现了List接口,都具有List中元素有序、不唯一的特点。

ArrayList实现了长度可变的数组,在内存中分配连续空间。遍历元素和随机访问元素的效率比较高;

LinkedList采用链表存储方式。插入、删除元素时效率比较高

实现原理相同,功能相同,底层都是哈希表结构,查询速度快,在很多情况下可以互用

1)哈希表的查询速度特别快,时间复杂度为O(1)。

4)向哈希表中添加数据的原理:当向集合Set中增加对象时,首先集合计算要增加对象的hashCode码,根据该值来得到一个位置用来存放当前对象,如在该位置没有一个对象存在的话,那么集合Set认为该对象在集合中不存在,直接增加进去。如果在该位置有一个对象存在的话,接着将准备增加到集合中的对象与该位置上的对象进行equals方法比较,如果该equals方法返回false,那么集合认为集合中不存在该对象,在进行一次散列,将该对象放到散列后计算出的新地址里。如果equals方法返回true,那么集合认为集合中已经存在该对象了,不会再将该对象增加到集合中了。

5)在哈希表中判断两个元素是否重复要使用到hashCode()和equals()。hashCode决定数据在表中的存储位置,而equals判断是否存在相同数据。

6) Y=K(X) :K是函数,X是哈希码,Y是地址

1)TreeSet集合,元素不允许重复且有序(自然顺序)

2)TreeSet采用树结构存储数据,存入元素时需要和树中元素进行对比,需要指定比较策略。

3)可以通过Comparable(外部比较器)和Comparator(内部比较器)来指定比较策略,实现了Comparable的系统类可以顺利存入TreeSet。自定义类可以实现Comparable接口来指定比较策略。

4)可创建Comparator接口实现类来指定比较策略,并通过TreeSet构造方法参数传入。这种方式尤其对系统类非常适用。

6. 集合和数组的比较

数组不是面向对象的,存在明显的缺陷,集合完全弥补了数组的一些缺点,比数组更灵活更实用,可大大提高软件的开发效率而且不同的集合框架类可适用于不同场合。具体如下:

1)数组的效率高于集合类.

2)数组能存放基本数据类型和对象,而集合类中只能放对象。

3)数组容量固定且无法动态改变,集合类容量动态改变。

4)数组无法判断其中实际存有多少元素,length只告诉了array的容量。

5)集合有多种实现方式和不同的适用场合,而不像数组仅采用顺序表方式。

6)集合以类的形式存在,具有封装、继承、多态等类的特性,通过简单的方法和属性调用即可实现各种复杂操作,大大提高软件的开发效率

1)Collection是Java提供的集合接口,存储一组不唯一,无序的对象。它有两个子接口List和Set。

2)Java中还有一个Collections类,专门用来操作集合类 ,它提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。

  • List 接口存储一组不唯一,有序(插入顺序)的对象。
  • Set 接口存储一组唯一,无序的对象。
  • Map接口存储一组键值对象,提供key到value的映射。key无序,唯一。value不要求有序,允许重复。(如果只使用key存储,而不使用value,那就是Set)

9. Map的实现类中,哪些是有序的,哪些是无序的,有序的是如何保证其有序性,你觉得哪个有序性性能更高,你有没有更好或者更高效的实现方式?

3. LinkedHashMap底层存储结构是哈希表+链表,链表记录了添加数据的顺序

4. TreeMap底层存储结构是二叉树,二叉树的中序遍历保证了数据的有序性

5. LinkedHashMap有序性能比较高,因为底层数据存储结构采用的哈希表

ArrayList 和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized 方法(线程安全),通常性能上较ArrayList 差,而LinkedList 使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,其实对内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快。Vector属于遗留容器(早期的JDK中使用的容器,除此之外Hashtable、Dictionary、BitSet、Stack、Properties都是遗留容器),现在已经不推荐使用,但是由于ArrayList和LinkedListed都是非线程安全的,如果需要多个线程操作同一个容器,那么可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这其实是装潢模式最好的例子,将已有对象传入另一个类的构造器中创建新的对象来增加新功能)。

11. List、Map、Set 三个接口,存取元素时,各有什么特点?

List以特定索引来存取元素,可有重复元素。

Set不能存放重复元素(用对象的equals()方法来区分元素是否重复)。Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一。Set和Map容器都有基于哈希存储和排序树(红黑树)的两种实现版本,基于哈希存储的版本理论存取时间复杂度为O(1),而基于排序树版本的实现在插入或删除元素时会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。

TreeSet要求存放的对象所属的类必须实现Comparable接口,该接口提供了比较元素的compareTo()方法,当插入元素时会回调该方法比较元素的大小。

TreeMap要求存放的键值对映射的键必须实现Comparable接口从而根据键对元素进行排序。

Collections工具类的sort方法有两种重载的形式,第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较;第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是是通过接口注入比较元素大小的算法,也是对回调模式的应用。

1.4 多线程相关的面试题

要编写一个多线程安全(Thread-safe)的程序是困难的,为了让线程共享资源,必须小心地对共享资源进行同步,同步带来一定的效能延迟,而另一方面,在处理同步的时候,又要注意对象的锁定与释放,避免产生死结,种种因素都使得编写多线程程序变得困难。

尝试从另一个角度来思考多线程共享资源的问题,既然共享资源这么困难,那么就干脆不要共享,何不为每个线程创造一个资源的复本。将每一个线程存取数据的行为加以隔离,实现的方法就是给予每个线程一个特定空间来保管该线程所独享的资源。

2. 说说乐观锁与悲观锁

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

3. 在Java中怎么实现多线程?描述线程状态的变化过程。

当多个线程访问同一个数据时,容易出现线程安全问题,需要某种方式来确保资源在某一时刻只被一个线程使用。需要让线程同步,保证数据安全线程同步的实现方案:同步代码块和同步方法,均需要使用synchronized关键字

  • 线程同步的好处:解决了线程安全问题
  • 线程同步的缺点:性能下降,可能会带来死锁

4. 在多线程编程里,wait方法的调用方式是怎样的?

wait方法是线程通信的方法之一,必须用在 synchronized方法或者synchronized代码块中,否则会抛出异常,这就涉及到一个“锁”的概念,而wait方法必须使用上锁的对象来调用,从而持有该对象的锁进入线程等待状态,直到使用该上锁的对象调用notify或者notifyAll方法来唤醒之前进入等待的线程,以释放持有的锁。

线程是一个动态执行过程,它有一个从产生到死亡的过程,共五种状态:

  • 新建(new Thread)当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
  • 就绪(runnable)线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();
  • 运行(running)线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
  • 死亡(dead)当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
  • 自然终止:正常运行run()方法后终止
  • 异常终止:调用stop()方法让一个线程终止运行
  • 堵塞(blocked)由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
  • 正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
  • 正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
  • 被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

6. 进程和线程的区别是什么?

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位.

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.

7. 创建n多个线程,如何保证这些线程同时启动?看清,是“同时”。

用一个for循环创建线程对象,同时调用wait()方法,让所有线程等待;直到最后一个线程也准备就绪后,调用notifyAll(), 同时启动所有线程。

8. 同步和异步有何异同,在什么情况下分别使用它们?

1.如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。

2.当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。

3.举个例子: 打电话是同步 发消息是异步

sleep是线程类(Thread)的方法;作用是导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复;调用sleep()不会释放对象锁。

wait是Object类的方法;对此对象调用wait方法导致本线程放弃对象锁,进入等 待此对象的等待锁定池。只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池,准备获得对象锁进行运行状态。

① sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;

② 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;

④ sleep()方法比yield()方法(跟操作系统相关)具有更好的可移植性。

11. 当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法?

其它线程只能访问该对象的非同步方法,同步方法则不能进入,只有等待当前线程执行完毕释放锁资源之后,其他线程才有可能进行执行该同步方法!

12. 请说出与线程同步相关的方法。

1. wait():使一个线程处于等待(阻塞)状态,并且释放所持有的对象的锁;

2. sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException 异常;

3. notify():唤醒一个处于等待状态的线程,当然在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且与优先级无关;

4. notityAll():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争;

5. JDK 1.5通过Lock接口提供了显式(explicit)的锁机制,增强了灵活性以及对线程的协调。Lock接口中定义了加锁(lock())和解锁(unlock())的方法,同时还提供了newCondition()方法来产生用于线程之间通信的Condition对象;

6. JDK 1.5还提供了信号量(semaphore)机制,信号量可以用来限制对某个共享资源进行访问的线程的数量。在对资源进行访问之前,线程必须得到信号量的许可(调用Semaphore对象的acquire()方法);在完成对资源的访问后,线程必须向信号量归还许可(调用Semaphore对象的release()方法)。

13. 编写多线程程序有几种实现方式?

Java 5以前实现多线程有两种实现方法:一种是继承Thread类;另一种是实现Runnable接口。两种方式都要通过重写run()方法来定义线程的行为,推荐使用后者,因为Java中的继承是单继承,一个类有一个父类,如果继承了Thread类就无法再继承其他类了,同时也可以实现资源共享,显然使用Runnable接口更为灵活。

synchronized关键字可以将对象或者方法标记为同步,以实现对对象和方法的互斥访问,可以用synchronized(对象) { … }定义同步代码块,或者在声明方法时将synchronized作为方法的修饰符。在第60题的例子中已经展示了synchronized关键字的用法。

启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM 调度并执行,这并不意味着线程就会立即运行。run()方法是线程启动后要进行回调(callback)的方法。

16. 线程的基本状态以及状态之间的关系?

除去起始(new)状态和结束(finished)状态,线程有三种状态,分别是:就绪(ready)、运行(running)和阻塞(blocked)。其中就绪状态代表线程具备了运行的所有条件,只等待CPU调度(万事俱备,只欠东风);处于运行状态的线程可能因为CPU调度(时间片用完了)的原因回到就绪状态,也有可能因为调用了线程的yield方法回到就绪状态,此时线程不会释放它占有的资源的锁,坐等CPU以继续执行;运行状态的线程可能因为I/O中断、线程休眠、调用了对象的wait方法而进入阻塞状态(有的地方也称之为等待状态);而进入阻塞状态的线程会因为休眠结束、调用了对象的notify方法或notifyAll方法或其他线程执行结束而进入就绪状态。注意:调用wait方法会让线程进入等待池中等待被唤醒,notify方法或notifyAll方法会让等待锁中的线程从等待池进入等锁池,在没有得到对象的锁之前,线程仍然无法获得CPU的调度和执行。

块中释放(这是释放外部资源的最好的地方)。

start方法:用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。通过调用Thread类的start()方法来启动一个线程,这时此线程处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,Run方法运行结束,此线程随即终止。

2) run():run()方法只是类的一个普通方法而已,如果直接调用run方法,程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码,这样就没有达到写线程的目的。

19. 线程的生命周期

当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。

线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。

线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。

当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。

自然终止:正常运行run()方法后终止

异常终止:调用stop()方法让一个线程终止运行

由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。

正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。

正在等待:调用wait()方法。(调用motify()方法回到就绪状态)

被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)

20. 说说关于同步锁的更多细节

Java中每个对象都有一个内置锁。

当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁。获得一个对象的锁也称为获取锁、锁定对象、在对象上锁定或在对象上同步。

当程序运行到synchronized同步方法或代码块时才该对象锁才起作用。

一个对象只有一个锁。所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回)锁。这也意味着任何其他线程都不能进入该对象上的synchronized方法或代码块,直到该锁被释放。

释放锁是指持锁线程退出了synchronized同步方法或代码块。

1.5 IO流相关的面试题

1. Java中如何实现序列化,有什么意义

序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决对象流读写操作时可能引发的问题(如果不进行序列化可能会存在数据乱序的问题)。

2. Java 中有几种类型的流?

两种流分别是字节流,字符流。

字节流继承于InputStream、OutputStream,字符流继承于Reader、Writer。在 包中还有许多其他的流,主要是为了提高性能和使用方便。

3. 输入流和输出流联系和区别,节点流和处理流联系和区别

首先,你要明白什么是“流”。直观地讲,流就像管道一样,在程序和文件之间,输入输出的方向是针对程序而言,向程序中读入东西,就是输入流,从程序中向外读东西,就是输出流。

输入流是得到数据,输出流是输出数据,而节点流,处理流是流的另一种划分,按照功能不同进行的划分。节点流,可以从或向一个特定的地方(节点)读写数据。处理流是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

4. 字符流字节流联系区别;什么时候使用字节流和字符流?

字符流和字节流是流的一种划分,按处理照流的数据单位进行的划分。两类都分为输入和输出操作。在字节流中输出数据主要是使OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。这四个都是抽象类。

字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。字节流是最基本的,所有的InputStrem和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的 但实际中很多的数据是文本,又提出了字符流的概念,它是按虚拟机的编码来处理,也就是要进行字符集的转化

5. 说明缓冲流的优点和原理

不带缓冲的流的工作原理:

它读取到一个字节/字符,就向用户指定的路径写出去,读一个写一个,所以就慢了。

带缓冲的流的工作原理:

读取到一个字节/字符,先不输出,等凑足了缓冲的最大容量后一次性写出去,从而提高了工作效率

6. 序列化的定义、实现和注意事项

想把一个对象写在硬盘上或者网络上,对其进行序列化,把他序列化成为一个字节流。

1)实现接口Serializable Serializable接口中没有任何的方法,实现该接口的类不需要实现额外的方法。

2)如果对象中的某个属性是对象类型,必须也实现Serializable接口才可以,序列化对静态变量无效

3)如果不希望某个属性参与序列化,不是将其static,而是transient串行化保存的只是变量的值,对于变量的任何修饰符,都不能保存序列化版本不兼容

7. 使用IO流完成文件夹复制

// 刷新此缓冲的输出流 //检查目标目录,如不存在则创建 // 遍历源目录下的文件或目录 // 准备复制的源文件夹 // 准备复制的目标文件夹

Java BIO :同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。

Java NIO :同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。

Java AIO:异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。

NIO比BIO的改善之处是把一些无效的连接挡在了启动线程之前,减少了这部分资源的浪费(因为我们都知道每创建一个线程,就要为这个线程分配一定的内存空间)

AIO比NIO的进一步改善之处是将一些暂时可能无效的请求挡在了启动线程之前,比如在NIO的处理方式中,当一个请求来的话,开启线程进行处理,但这个请求所需要的资源还没有就绪,此时必须等待后端的应用资源,这时线程就被阻塞了。

OutOf MemoryError这种错误可以细分为多种不同的错误,每种错误都有自身的原因和解决办法,如下所示:

  • 错误原因:此OOM是由于JVM中heap的最大值不满足需要。
  • 解决方法:1) 调高heap的最大值,即-Xmx的值调大。2) 如果你的程序存在内存泄漏,一味的增加heap空间也只是推迟该错误出现的时间而已,所以要检查程序是否存在内存泄漏。

2. 列举常见的运行时异常

path中jdk的版本调整与jar包匹配后,解决异常。

4. try{}里有一个return语句,那么紧跟在这个try后的finally{}里的code会不会被执行,什么时候被执行,在return前还是后?

在方法返回调用者前执行。Java允许在finally中改变返回值的做法是不好的,因为如果存在finally代码块,try中的return语句不会立马返回调用者,而是记录下返回值待finally代码块执行完毕之后再向调用者返回其值,然后如果在finally中修改了返回值,这会对程序造成很大的困扰,C#中就从语法上规定不能做这样的事。

Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java 中,每个异常都是一个对象,它是Throwable 类或其子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。Java 的异常处理是通过5 个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throw)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理;try用来指定一块预防所有“异常”的程序;catch 子句紧跟在try块后面,用来指定你想要捕捉的“异常”的类型;throw 语句用来明确地抛出一个“异常”;throws用来标明一个成员函数可能抛出的各种“异常”;finally 为确保一段代码不管发生什么“异常”都被执行一段代码;可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try 语句,“异常”的框架就放到栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种“异常”进行处理,栈就会展开,直到遇到有处理这种“异常”的try 语句。

Error类,表示仅靠程序本身无法恢复的严重错误,比如说内存溢出、动态链接异常、虚拟机错误。应用程序不应该抛出这种类型的对象。假如出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以在进行程序设计时,应该更关注Exception类。

Exception类,由Java应用程序抛出和处理的非严重错误,比如所需文件没有找到、零作除数,数组下标越界等。它的各种不同子类分别对应不同类型异常。可分为两类:Checked异常和Runtime异常

1)程序首先执行可能发生异常的try语句块。

2)如果try语句没有出现异常则执行完后跳至finally语句块执行;

3)如果try语句出现异常,则中断执行并根据发生的异常类型跳至相应的catch语句块执行处理。

4)catch语句块可以有多个,分别捕获不同类型的异常。

5)catch语句块执行完后程序会继续执行finally语句块。

finally语句是可选的,如果有的话,则不管是否发生异常,finally语句都会被执行。需要注意的是即使try和catch块中存在return语句,finally语句也会执行,是在执行完finally语句后再通过return退出。

  • throw用于程序员自行产生并抛出异常;
  • throws用于声明在该方法内抛出了异常

2) 使用的位置不同:

  • throw位于方法体内部,可以作为单独语句使用;
  • throws必须跟在方法参数列表的后面,不能单独使用。
  • throw抛出一个异常对象,且只能是一个;
  • throws后面跟异常类,而且可以有多个。

关注我们的公众号 慕阳源码 我们为您提供

原创的Java面试题大全

回复资源获得"Java 最全教程"

我要回帖

更多关于 datetime在java中的类型 的文章

 

随机推荐