Java刷题总结(面试)

 1、String类

 String不可变

java 中String是 immutable的,也就是不可变,一旦初始化,其引用指向的内容是不可变的。

也就是说,String str = “aa”;str=“bb”;第二句不是改变“aa”所存储地址的内容,而是另外开辟了一个空间用来存储“bb”;同时由str指向 原来的“aa”,现在已经不可达,GC时会自动回收。 因此String作为参数传进来时候,str= "test ok"; 实际给副本引用str指向了新分配的地址,该地址存储“test ok”。 因此,原先的str仍然指向“good”

String不能被继承 

String类由final修饰,所以不能被继承。 

StringBuffer和StringBuilder

 StringBuffer、StringBuilder都代表可变的字符串对象。

它们有共同的父类 AbstractStringBuilder,并且两个类的构造方法和成员方法也基本相同。

StringBuffer是线程安全的,而StringBuilder是非线程安全的,所以StringBuilder性能略高。

一般情况下,要创建一个内容可变的字符串,建议优先考虑StringBuilder类。 

new和“ ”

  • 直接使用 "hello" 的字符串直接量时,JVM将会使用常量池来管理这个字符串;

  • 当使用 new String("hello") 时,JVM会先使用常量池来管理 "hello" 直接量,再调用String类的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中。

显然,采用new的方式会多创建一个对象出来,会占用更多的内存,所以一般建议使用直接量的方式创建字符串。 

2、接口

接口里只能包含抽象(abstract)方法、静态(static)方法、默认(default)方法和私有(private)方法,不能为普通方法提供方法实现。


 接口里只能定义静态常量(static final),不能定义普通成员变量。


接口里不包含构造器。


接口里不能包含初始化块。


一个类可以直接实现多个接口。 


接口不能被实例化。


接口包含抽象方法,实现接口的普通子类都必须实现这些抽象方法。


 interface中的方法默认为public abstract 的 ,变量默认为public static final


 3、Object的基本方法

Object类并不包含copy()方法,题目中描述的应该是clone()方法。

copy()方法属于java.nio.file.Files类,其作用是将字节从文件复制到I /O流或从I /O流复制到文件。

4、Collection和Collections

5、Java概念

A、java异常和错误的基类Throwable,包括Exception和Error

C、java是面向对象的,但是不是所有的都是对象,基本数据类型就不是对象,所以才会有封装类的;

D、如果是等待清理队列中如果又被调用,则不会执行finallize方法

E、JAVA跨平台性    实现在任意平台的java程序都可以在其他平台运行;采用高版本的JDK编写的程序,在低版本的JRE中无法运行。

6、互斥锁

A:用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这个段代码。

B:对于volatile类型的变量,系统每次用到他的时候都是直接从对应的内存当中提取,**而不会利用cache当中的原有数值,**以适应它的未知何时会发生的变化,系统对这种变量的处理不会做优化——显然也是因为它的数值随时都可能变化的情况。

C:

​将内存中的java对象放到硬盘叫做序列化,硬盘到内存叫做反序列化;

序列化(Serialize)(将java对象的状态保存下来的过程);

参与序列化和反序列化的对象,必须实现Serializable接口;

凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号。这样,以后这个类即使代码修改了,但是版本号不变,java虚拟机会认为是同一个类。

序列化是通过实现java.io.Serializable接口来完成的。这个接口是一个标记接口,意味着它不包含任何方法

7、构造方法

子类的构造方法总是先调用父类的构造方法,如果子类的构造方法没有明显地指明使用父类的哪个构造方法,子类就调用父类不带参数的构造方法。
而父类没有无参的构造函数,所以子类需要在自己的构造函数中显示的调用父类的构造函数。

因此需要在子类的构造方法中添加super(”nm“) 

在创造派生类的过程中首先创建基类对象,然后才能创建派生类。

创建基类即默认调用Base()方法,在方法中调用callName()方法,由于派生类中存在此方法,则被调用的callName()方法是派生类中的方法,此时派生类还未构造,所以变量baseName的值为null

答案:

子类构造方法在调用时必须先调用父类的,由于父类没有无参构造,必须在子类中显式调用,修改子类构造方法如下即可: public Derived(String s){ super("s"); System.out.print("D"); }

总结:

1.写一个类,如果没有写构造函数,那么这类默认会有一个无参的构造函数。如果写构造函数了,那么就不会有默认的无参构造函数, 以自己写的构造函数为准。

2.子类在写构造函数的时候,第一行必须用super 关键字调用父类的任一构造函数。

3.用super调用父类的构造函数时,如果调用的是父类无参构造函数,则super()可以不用写,如果是有参构造函数,则必须使用super显示调用。
 

A:静态成员变量或静态代码块>main方法>非静态成员变量或非静态代码块>构造方法

B:构造器本身并没有任何返回值。

特点:

构造方法的方法名与类名相同

构造方法没有返回值类型,也不写void

构造方法可以重载

代码块:

分类:静态代码块和实例代码块

静态代码块:static修饰的代码块,在类加载时执行,且只执行一次。因为类就加载一次了。

实例代码块:没有static修饰的代码块,创建对象时执行,每创建一次对象加载一次。

实例代码块在执行构造方法之前执行。所以优先级高于构造方法。

 8、static

static修饰的类可以被继承。


 static关键字的作用是把类的成员变成类相关,而不是实例相关,即static修饰的成员属于整个类,而不属于单个对象。


static关键字不可修饰外部类,但可修饰内部类。 


  • 类变量:它随类的信息存储在方法区,并不随对象存储在堆中,类变量可以通过类名来访问,也可以通过对象名来访问,但建议通过类名访问它。

  • 类方法:可以通过类名访问,也可以通过对象名访问,建议通过类名访问它。

  • 静态块:静态块属于类,它在类加载的时候被隐式调用一次,之后便不会被调用了。

  • 静态内部类:被static修饰的内部类叫静态内部类。静态内部类可以包含静态成员,也可以包含非静态成员。静态内部类不能访问外部类的实例成员,只能访问外部类的静态成员。外部类的所有方法、初始化块都能访问其内部定义的静态内部类。


9、设计模式

MVC只是将分管不同功能的逻辑代码进行了隔离,增强了可维护和可扩展性,增强代码复用性,因此可以减少代码重复。但是不保证减少代码量,多层次的调用模式还有可能增加代码量。

一般来讲,使用设计模式都会增加代码量。

10、Spring的事务传播

PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。  

 PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。 

 PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 

 PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 

 PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 

 PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

 11、集合类,异常,子类

A:可以不必事先知道对象类型,默认就Object类型

C:不可以是变量,必须是被final修饰的常量

D:子类可以访问父类受保护的成员 

12、线程

 A、ConcurrentHashMap实际上是 HashTable的升级版,使用segment来分段和管理锁,并不是synchronized;

B、HashMap实现的接口有:Serializable, Cloneable, Map<K,V> ,没有实现Collction

C、Arrays.asList()方法返回的列表是Arrays.ArrayList类型的,并不是java.util.ArrayList; 

A: HashSet 它不是线程安全的,属于Set接口下的实现类,Set下的实现类特征就是无序,不允许存储相同的对象

B: ConcurrentHashMap 它是线程安全的HashMap实现,特征也相似,其中存储的值对象可以重复,键对象不能重复

C: Collection接口是List接口和Set接口的父接口,通常情况下不被直接使用

D: ArrayList线程不安全的,底层是数组实现,允许存放重复对象

基本上我们平常用到的都是非线程安全的集合类,因为要使线程安全,是要加锁来实现的,势必造成性能降低。如hashset、hashmap、arraylist、linkedlist、treemap、treeset、stringbulider等。

像stringbuhffer、vector、hashtable这些都是专用于多线程的,再者以concurrent(意为:同时发生的)为前缀的集合类大多是线程安全的。

答案为B

A: stop()方法是强制当前线程停止运行,并抛出ThreadDead错误。

B:中断线程比较安全的做法是引入共享变量。

C:suspend()方法是临时挂起当前线程。

D:yield()方法是使当前执行暂时停止执行而让其他线程运行。

13、super和this关键字

super指向当前对象的父类对象

 B:super()必须在第一行的原因是: 子类是有可能访问父类对象的, 比如在构造函数中使用父类对象的成员函数和变量, 在成员初始化使用了父类, 在代码块中使用了父类等等, 所以为保证在子类可以访问父类对象之前,一定要完成对父类对象的初始化。

关于this()必须在第一行的原因,我们假设这样一种情况,,类B是类A的子类, 如果this()可以在构造函数的任意行使用, 那么当程序运行到构造函数B()的第一行,发现没有调用this()和super(),那么就会自动在第一行补齐super() 来完成对父类对象的初始化, 然后返回子类的构造函数继续执行, 当运行到构造函数B()的"this() ;"时, 调用B类对象的构造函数, 还会对父类对象再次初始化!,这就造成了资源的浪费,以及某些意想不到的错误。

D:无论是this()还是super()指的都是对象,而static环境中是无法使用非静态变量的。 

14、java classloader

 C:JVM在判定两个class是否相同时,不仅要判断两个类名是否相同,而且要判断是否由同一个类加载器实例加载的。

15、实例的调用

题目应该问的是错误的,选C

C;非静态方法只能通过实例对象来调用,不能直接通过类名调用。静态方法(static)才能通过类名直接调用

16、异或符号

^表示异或 就是相同是0 不同是1

14是1110

3是0011

所以14^3=1101,即输出13

17、多态

 18、事务隔离级别

A:Java程序可以指定事务隔离级别,但实现隔离级别的是数据库系统。

B:Hibernate是开放源代码的对象关系映射框架,它对JDBC做了非常轻量级的封装。

D:JDBC全称是Java Database connect,它是一套用于执行SQL语句的Java API。

Hibernate和JDBC均是程序与数据库连接的桥梁,无法实现事务隔离级别。

19、内存

首先理解一下内存泄漏的概念,内存泄漏就是对象引用消失了,对象内存却没有被回收。

A答案:FullGC 是老年代内存空间不足的时候,才会触发的,老年代一般是生命周期较长的对象或者大对象,频繁的 FullGC 不会可能会影响程序性能(因为内存回收需要消耗CPU等资源),但是并不会直接导致内存泄漏。

B 答案:JVM奔溃的可能是内存溢出引起的,也可能是其他导致 JVM崩溃的操作,例如设置了错误的JVM参数等。

C 答案:内存异常,最常见的 就是 StackOverFlow 了把,内存溢出,其实内存泄漏的最终结果就是内存溢出。所以,基本上C是对的答案。

D 答案:Java 进程异常消失,这个明显不对的。

20、抽象类

接口里只能包含抽象方法、静态方法、默认方法和私有方法,不能为普通方法提供方法实现;

抽象类则完全可以包含普通方法。


接口里只能定义静态常量,不能定义普通成员变量;

抽象类里则既可以定义普通成员变量,也可以定义静态常量。


 接口里不包含构造器;

抽象类里可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。


 接口里不能包含初始化块;

但抽象类则完全可以包含初始化块。


 一个类最多只能有一个直接父类,包括抽象类;

但一个类可以直接实现多个接口,通过实现多个接口可以弥补Java单继承的不足。


 接口和抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他类实现和继承。


 接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。


抽象类中可以没有抽象方法,但是抽象方法必须在抽象类中或者接口中。

21、流

已知zipname是一个压缩文件名,则zipname在下列代码中出现的正确位置是

ZipInputStream zin = new ZipInputStream(new FileInputStream(1));
ZipEntry entry;
while((entry=zin.getNextEntry(2))!=null){
    fileCombo.addItem(entry.getName(3));
    zin.closeEntry(4);
}

 答案为1

当需要输入一个zip文件时,要将zip文件作为FileInputStrem构造方法的参数,即题目中的1处。

1、stream结尾都是字节流,reader和writer结尾都是字符流 两者的区别就是读写的时候一个是按字节读写,一个是按字符。

2、在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流。

3、只是读写文件,和文件内容无关的,一般选择字节流。
 

22、Socket

23、Volatile

       一般都是和const对应 

  • volatile对应的变量可能在你的程序本身不知道的情况下发生改变
  • 比如多线程的程序,共同访问的内存当中,多个程序都可以操纵这个变量
  • 你自己的程序,是无法判定何时这个变量会发生变化
  • volatile的措施,就是

    1. 每次从内存中取值,不从缓存中什么的拿值。这就保证了用 volatile修饰的共享变量,每次的更新对于其他线程都是可见的。

    2. volatile保证了其他线程的立即可见性,就没有保证原子性。

    3.由于有些时候对 volatile的操作,不会被保存,说明不会造成阻塞。不可用与多线程环境下的计数器。

A选项,volatile关键字对任意单个volatile变量的的读写操作可以保证原子性,但类似于volatile++这种复合操作就无法保证原子性了。如果需要对这种复合操作保证原子性,最好用synchronized关键字。即synchronized保证三大性,原子性,有序性,可见性,volatile保证有序性,可见性,不能保证原子性。

B选项,为了实现volatile的内存语义,编译器在生成字节码时会在指令序列中插入内存屏障来禁止特定类型的处理器重排序,以此来保证有序性。

C选项,可见性是指当多个线程并发访问共享变量时,一个线程对共享变量的修改,其它线程能够立即看到。对于一个volatile变量的读,总是能看到对这个volatile变量最后的写入,保证了可见性。

D选项为干扰选项。

  • volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。但是volatile关键字只能用于变量而synchronized关键字可以修饰方法以及代码块。synchronized关键字在JavaSE1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁以及其它各种优化之后执行效率有了显著提升,实际开发中使用 synchronized 关键字的场景还是更多一些。
  • 多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞
  • volatile关键字能保证数据的可见性,但不能保证数据的原子性。synchronized关键字两者都能保证。
  • volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized关键字解决的是多个线程之间访问资源的同步性。

synchronized保证三大性,原子性,有序性,可见性

volatile保证有序性,可见性,不能保证原子性

数据库事务正确执行的四个基本要素,ACID(原子性,一致性,隔离性,持久性)

synchronized不是修饰变量的 它修饰方法或代码块或对象

Volatile修饰变量

24、值类型和引用类型

 

25、this

this不能在static的方法中使用 

A的答案中变量虽然为private,但因为main函数在该类中,所以即使private也仍可使用


this可以出现在类的构造方法中可以出现在非static修饰的成员方法中可以代表实例对象本身但不可以用来引用父类的成员变量


26、集合类

Collection

    -----List  有序,可以重复

               -----LinkedList    非同步

                ----ArrayList      非同步,实现了可变大小的元素数组

                ----Vector          同步

                         ------Stack

    -----Set   无序,不允许有相同的元素

             ----HashSet     线程不安全,存取速度快。底层是以哈希表实现的

             ----TreeSet        红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。

            ----LinkedHashSet        会保存插入的顺序。

           -----sortedSet        按升序维护其元素的集合

    -----Queue         代表一个先进先出(FIFO)的队列

Map        具有映射(key-value)结构

    -----HashTable        同步,实现一个key--value映射的哈希表;线程安全

    -----HashMap          非同步;HashMap的实例有两个参数影响其性能:“初始容量”,“加载因子”;通过拉链法解决哈希冲突;key-value都是储存在entry数组中的

    ----WeakHashMap   改进的HashMap,实现了“弱引用”,如果一个key不被引用,则被GC回收

    -----TreeMap   按key排序,key不重复

    -----IdentityHashMap  key可重复

A: HashSet 它不是线程安全的,属于Set接口下的实现类,Set下的实现类特征就是无序,不允许存储相同的对象

B: ConcurrentHashMap 它是线程安全的HashMap实现,特征也相似,其中存储的值对象可以重复,键对象不能重复

C: Collection接口是List接口和Set接口的父接口,通常情况下不被直接使用

D: ArrayList线程不安全的,底层是数组实现,允许存放重复对象


B、LinkedBlockingQueue是一个线程安全的阻塞队列,实现了先进先出等特性。
C、PriorityQueue不允许null值,入队和出队的时间复杂度是O(log(n))。
D、

PriorityQueue是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。

ConcurrentLinkedQueue是一个基于链接节点的线程安全队列,该队列的元素遵循FIFO原则
 

27、 JVM

JVM 内存可简单分为三个区:

1、堆区(heap):用于存放所有对象,是线程共享的(注:数组也属于对象)

2、栈区(stack):用于存放基本数据类型的数据和对象的引用,是线程私有的(分为:虚拟机栈和本地方法栈)

3、方法区(method):用于存放类信息、常量、静态变量、编译后的字节码等,是线程共享的(也被称为非堆,即 None-Heap)

Java 的垃圾回收器(GC)主要针对堆区

28、重载和重写

 重载就是方法名相同,但参数列表不同与返回值类型无关,属于重名方法

重写要求方法名返回值类型参数完全相同

重写要满足的条件:(好比父亲给儿子100块钱让儿子去花)

1.参数列表要完全相同——(你拿的就是100块钱,变不成别的,怎么花随你,但是钱数、参数列表不变)

2.返回类型是父类方法的返回类型的子类型——(返回值,可以说是你花100得到的是价值小于等于100的东西,你能买回来的一定在100之内)

3.访问权限不能大于父类方法权限——(就是访问修饰符要比父类的小于等于)

29、异常

异常类结构

Throwable是异常的顶层父类,它有两个直接子类,分别是Error、Exception。

Error是错误,一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断。

通常应用程序无法处理这些错误,因此应用程序不应该试图使用catch块来捕获Error对象。

在定义方法时,也无须在其throws子句中声明该方法可能抛出Error及其任何子类。

Exception是异常,它被分为两大类,分别是Checked异常和Runtime异常。所有的RuntimeException类及其子类的实例被称为Runtime异常;不是RuntimeException类及其子类的异常实例则被称为Checked异常。

Java认为Checked异常都是可以被处理(修复)的异常,所以Java程序必须显式处理Checked异常。如果程序没有处理Checked异常,该程序在编译时就会发生错误,无法通过编译。Runtime异常则更加灵活,Runtime异常无须显式声明抛出,如果程序需要捕获Runtime异常,也可以使用try...catch块来实现。

finally

不管try块中的代码是否出现异常,也不管哪一个catch块被执行,甚至在try块或catch块中执行了return语句,finally块总会被执行。


在finally块中使用了return、throw语句,将会导致try块、catch块中的return、throw语句失效。


30、泛型

泛型擦除

当把一个具有泛型信息的对象赋给另一个没有泛型信息的变量时,所有在尖括号之间的类型信息都将被扔掉。比如一个 List<String> 类型被转换为List,则该List对集合元素的类型检查变成了泛型参数的上限(即Object)。

List<String> list1 = ...; 
List list2 = list1; 
// list2将元素当做Object处理

31、反射

通过反射机制,我们可以实现如下的操作:

  • 程序运行时,可以通过反射获得任意一个类的Class对象,并通过这个对象查看这个类的信息;

  • 程序运行时,可以通过反射创建任意一个类的实例,并访问该实例的成员;

  • 程序运行时,可以通过反射机制生成一个类的动态代理类或动态代理对象。

32、内部类

内部类不能编译生成

· 内部类可以直接访问外部类的成员,包括私有

· 外部类要访问内部类的成员,必须创建对象

33、类成员变量修饰符

包外子类包内类内
publicyesyesyesyes
protectednoyesyesyes
defaultnonoyesyes
privatenononoyes

34、多态

通过方法重载,方法覆盖可以实现多态

父类引用指向子类对象可以实现多态

Java语言支持运行时多态


  • 26
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值