java面试题

今天给大家整理了一些笔试题,有时间的话我会尽可能的去整理更全面的问题,希望对大家有所帮助。

笔试

基础题

1:谈谈final,finally,finallize的区别

final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。内部类要访问局部变量,局部变量必须定义成final类型。
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。但是JVM不保证此方法总被调用

2:说说你知道的几种设计模式,并写出相关代码或画出类图(至少两种)。

这种问题肯定写的越多越好,所以这就很考研我们平时掌握的知识了。
建议答案:单例模式,抽线工厂模式,代理模式,模板方法模式,装饰模式,适配器模式。以上几种都是我们常用的。

单例模式(懒汉式):
该模式的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例

public class LazySingleton
{
    private static volatile LazySingleton instance=null;    //保证 instance 在所有线程中同步
    private LazySingleton(){}    //private 避免类在外部被实例化
    public static synchronized LazySingleton getInstance()
    {
        //getInstance 方法前加同步
        if(instance==null)
        {
            instance=new LazySingleton();
        }
        return instance;
    }
}

单例模式(饿汉式):
该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。

public class HungrySingleton
{
    private static final HungrySingleton instance=new HungrySingleton();
    private HungrySingleton(){}
    public static HungrySingleton getInstance()
    {
        return instance;
    }
}

抽象工厂模式:
(1) 抽象工厂:提供了产品的生成方法。

interface AbstractFactory
{
    public Product1 newProduct1();
    public Product2 newProduct2();
}

(2) 具体工厂:实现了产品的生成方法。

class ConcreteFactory1 implements AbstractFactory
{
    public Product1 newProduct1()
    {
        System.out.println("具体工厂 1 生成-->具体产品 11...");
        return new ConcreteProduct11();
    }
    public Product2 newProduct2()
    {
        System.out.println("具体工厂 1 生成-->具体产品 21...");
        return new ConcreteProduct21();
    }
}

代理模式:
在这里插入图片描述

public class ProxyTest
{
    public static void main(String[] args)
    {
        Proxy proxy=new Proxy();
        proxy.Request();
    }
}
//抽象主题
interface Subject
{
    void Request();
}
//真实主题
class RealSubject implements Subject
{
    public void Request()
    {
        System.out.println("访问真实主题方法...");
    }
}
//代理
class Proxy implements Subject
{
    private RealSubject realSubject;
    public void Request()
    {
        if (realSubject==null)
        {
            realSubject=new RealSubject();
        }
        preRequest();
        realSubject.Request();
        postRequest();
    }
    public void preRequest()
    {
        System.out.println("访问真实主题之前的预处理。");
    }
    public void postRequest()
    {
        System.out.println("访问真实主题之后的后续处理。");
    }
}

3:谈谈接口与抽象类的区别。

1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然
eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是publicstatic final类型,并且默认即为publicstatic final类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。

4:Overload和Override分别代表什么?有什么区别?

Overload是重载的意思,Override是覆盖的意思,也就是重写。
重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。

 重写Override表示子类中的方法可以与父类中的某个方法的名称和参
 数完全相同,通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,
 这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。
 子类覆盖父类的方法时,只能比父类抛出更少的异常,或者是抛出父类抛出的异常的子异常,
 因为子类可以解决父类的一些问题,不能比父类有更多的问题。
 子类方法的访问权限只能比父类的更大,不能更小。如果父类的方法是private类型,
 那么,子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。

至于Overloaded的方法是否可以改变返回值的类型这个问题,要看你倒底想问什么呢?
这个题目很模糊。如果几个Overloaded的方法的参数列表不一样,
它们的返回者类型当然也可以不一样。但我估计你想问的问题是:如果两个方法的参数列表完全一样,
是否可以让它们的返回值不同来实现重载Overload。
这是不行的,我们可以用反证法来说明这个问题,因为我们有时候调用
一个方法时也可以不定义返回结果变量,即不要关心其返回结果,
例如,我们调用map.remove(key)方法时,虽然remove方法有返回值,
但是我们通常都不会定义接收返回结果的变量,这时候假设该类中有两个名称和参数列表
完全相同的方法,仅仅是返回类型不同,java就无法确定编程者
倒底是想调用哪个方法了,因为它无法通过返回结果类型来判断。 

override可以翻译为覆盖,从字面就可以知道,它是覆盖了一个方法并且对其重写,以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般只是对方法进行了声明,而我们在实现时,就需要实现接口声明的所有方法。除了这个典型的用法以外,我们在继承中也可能会在子类覆盖父类中的方法。在覆盖要注意以下的几点:

1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果;
2、覆盖的方法的返回值必须和被覆盖的方法的返回一致;
3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类;
4、被覆盖的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。

Overload对我们来说可能比较熟悉,可以翻译为重载,它是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行。在使用重载要注意以下的几点:

1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int,float),但是不能为fun(int,int));

2、不能通过访问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
4、对于继承来说,如果某一方法在父类中是访问权限是priavte,那么就不能在子类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。

5:Integer与int的区别?

int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别,int则无法表达出未赋值的情况。

6:char型变量中能不能存贮一个中文汉字?为什么?

char型变量是用来存储Unicode编码的字符的,unicode编码字符集中包含了汉字,所以,char型变量中当然可以存储汉字啦。不过,如果某个特殊的汉字没有被包含在unicode编码字符集中,那么,这个char型变量中就不能存储这个特殊汉字。补充说明:unicode编码占用两个字节,所以,char类型的变量也是占用两个字节。

7:String s = new String(“xyz”);创建了几个StringObject?是否可以继承String类?

注:这道题是我自己遇到过次数最多的一道题,基本上好多笔试
都会有这道题

两个或一个都有可能,”xyz”对应一个对象,这个对象放在字符串常量缓冲区,常量”xyz”不管出现多少遍,都是缓冲区中的那一个。NewString每写一遍,就创建一个新的对象,它使用常量”xyz”对象的内容来创建出一个新String对象。如果以前就用过’xyz’,那么这里就不会创建”xyz”了,直接从缓冲区拿,这时创建了一个StringObject;但如果以前没有用过"xyz",那么此时就会创建一个对象并放入缓冲区,这种情况它创建两个对象。至于String类是否继承,答案是否定的,因为String默认final修饰,是不可继承的。

8:GC是什么?为什么要有GC?

GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。

9:List,Set, Map是否继承自Collection接口?
List,Set是,Map不是

10:ArrayList和Vector的区别

(1)同步性:
Vector是线程安全的,也就是说是它的方法之间是线程同步的,而ArrayList是线程序不安全的,它的方法之间是线程不同步的。如果只有一个线程会访问到集合,那最好是使用ArrayList,因为它不考虑线程安全,效率会高些;如果有多个线程会访问到集合,那最好是使用Vector,因为不需要我们自己再去考虑和编写线程安全的代码。
(2)数据增长:即Vector增长原来的一倍,ArrayList增加原来的0.5倍。

11:==和equals区别

“== ” 比较的是两个引用在内存中指向的是不是同一对象(即同一内存空间),也就是说在内存空间中的存储位置是否一致。如果两个对象的引用相同时(指向同一对象时),“==”操作符返回true,否则返回flase。
equals用来比较某些特征是否一样。我们平时用的String类等的equals方法都是重写后的,实现比较两个对象的内容是否相等。

12:String、StringBuffer和StringBuilder区别

  1. 数据可变和不可变:
    String底层使用一个不可变的字符数组private final char value[];所以它内容不可变。
    StringBuffer和StringBuilder都继承了AbstractStringBuilder底层使用的是可变字符数组:char[] value;
  2. 线程安全:
    StringBuilder是线程不安全的,效率较高;而StringBuffer是线程安全的,效率较低。
    通过他们的append()方法来看,StringBuffer是有同步锁,而StringBuilder没有:

13:ArrayList和LinkedList区别?

注:这个问题我在技面的时候也被问到了哦!

1、ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2、对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3、对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

14: 线程创建方式

线程的重要性就不要我多说了,无论是想对于基础的知识还是
高级的知识都是多频考点与问点。

方法一:继承Thread类,作为线程对象存在(继承Thread对象)
方法二:实现runnable接口,作为线程任务存在
方法三:匿名内部类创建线程对象
方法四:创建带返回值的线程(实现Callable) :

这种方法带有返回值,其他方式可以不了解,但是基本的方法一、
方法二以及	这种方法一定要掌握。
返回指定泛型的call方法。然后调用FutureTask对象的get方法得到
call方法的返回值。

方法五:定时器Timer
方法六:线程池创建线程
方法七:利用java8新特性 stream 实现并发:这个就是用到lambda了

15:两个对象的hashCode相同,则equals也一定为true,对吗?

这块肯定是有争议的。面试的时候这样答:如果按照官方设计要求来打代码的话,hashcode一定相等。但是如果不按官方照设计要求、不重写hashcode方法,就会出现不相等的情况。

16:Math.round(-2.5)等于多少?

+0.5后向下取整。所以结果是-2。

注:千万不要把他记成四舍五入

17:JDK1.8新特性

1、lambda表达式
2、函数是接口
3、流式(stream)处理
4、新时间日期API
5、接口中的默认方法和静态方法
6、方法引用和构造器调用

18:TCP和UDP区别

1、TCP面向连接,UDP面向非连接
2、TCP提供可靠的服务(数据传输无差错、不丢失、不重复、按序到达),UDP不可靠
3、TCP面向字节流,UDP面向报文
4、TCP数据传输慢,UDP数据传输快
5、TCP首部开销20字节,UDP8字节

19:为什么要三次握手?

保持信息对等。
防止请求超时导致脏连接。

20:两次握手会怎样?

如果两次握手就创建连接,传输完数据并释放连接后,第一个超时的连接请求才到达服务器,服务器会认为是客户端创建新连接的请求,然后创建连接。此时客户端的状态不是SYN_SENT,所以会直接丢弃服务器传来的确认数据,导致最后只是服务器单方面建立了连接。

网络基础部分除去个别公司考的不多,但不能不看哦!还可以看一下常用的端口号等知识。字符串的相关方法以及数组这里我没有提及,但是一定一定一定要会,尤其字符串的方法,如:切割,截取字符等方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值