javaSE八股文

javaSE八股文

1.多线程部分

创建线程有几种不同的方式?你喜欢哪一种?为什么?

有三种方式可以用来创建线程:

  • 继承Thread类

  • 实现Runnable

  • 实现Callable接口、使用Executor框架来创建线程池(实现Callable接口-创建ExecutorService 实例-service.submit(接口实现类)-service.shutdown) 实现Runnable接口这种方式更受欢迎,因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下,这需要多继承(而Java不支持多继承),只能实现接口。同时,线程池也是非常高效的,很容易实现和使用。

Thread中的run()和start()方法有何区别?

t.start()会导致run()方法被调用,run()方法中的内容称为线程体,它就是这个线程需要执行的工作。 用start()来启动线程,实现了真正意义上的启动线程,此时会出现异步执行的效果,即在线程的创建和启动中所述的随机性。 而如果使用run()来启动线程,就不是异步执行了,而是同步执行,不会达到使用线程的意义

sleep和wait的区别:

1、sleep是Thread的静态方法,wait是Object的方法,任何对象实例都能调用。

2、sleep不会释放锁,它也不需要占用锁。wait会释放锁,但调用它的前提是当前线程占有锁(即代码要在synchronized中)。

3、它们都可以被interrupted方法中断。

锁的分类

可重入锁:Synchronized和ReentrantLook都是可重入锁,锁的可重入性标明了锁是针对线程分配方式而不是针对方法。例如调用Synchronized方法A中可以调用Synchronized方法B,而不需要重新申请锁。

读写锁:按照数据库事务隔离特性的类比读写锁,在访问统一个资源(一个文件)的时候,使用读锁来保证多线程可以同步读取资源。ReadWriteLock是一个读写锁,通过readLock()获取读锁,通过writeLock()获取写锁。

可中断锁:可中断是指锁是可以被中断的,Synchronized内置锁是不可中断锁,ReentrantLock可以通过lockInterruptibly方法中断显性锁。例如线程B在等待等待线程A释放锁,但是线程B由于等待时间太久,可以主动中断等待锁。

公平锁:公平锁是指尽量以线程的等待时间先后顺序获取锁,等待时间最久的线程优先获取锁。synchronized隐性锁是非公平锁,它无法保证等待的线程获取锁的顺序,ReentrantLook可以自己控制是否公平锁。

Synchronized和Lock比较

实现:

  • Synchronized:底层使用指令码方式来控制锁的,映射成字节码指令就是增加来两个指令:monitorenter和monitorexit。当线程执行遇到monitorenter指令时会尝试获取内置锁,如果获取锁则锁计数器+1,如果没有获取锁则阻塞;当遇到monitorexit指令时锁计数器-1,如果计数器为0则释放锁。

  • Lock:底层是CAS乐观锁,依赖AbstractQueuedSynchronizer类,把所有的请求线程构成一个CLH队列。而对该队列的操作均通过Lock-Free(CAS)操作。

  • Synchronized是关键字,内置语言实现,Lock是接口。

  • Synchronized在线程发生异常时会自动释放锁,因此不会发生异常死锁。Lock异常时不会自动释放锁,所以需要在finally中实现释放锁。

  • Lock是可以中断锁,Synchronized是非中断锁,必须等待线程执行完成释放锁。

  • Lock可以使用读锁提高多线程读效率。

同步方法和同步代码块的区别是什么?

在Java语言中,每一个对象有一把锁。线程可以使用synchronized关键字来获取对象上的锁。synchronized关键字可应用在方法级别(粗粒度锁:这里的锁对象可以是This)或者是代码块级别(细粒度锁:这里的锁对象就是任意对象)

  • 同步方法默认用this或者当前类class对象作为锁;

  • 同步代码块可以选择以什么来加锁,比同步方法要更细颗粒度,我们可以选择只同步会发生同步问题的部分代码而不是整个方法;

  • 同步方法使用关键字 synchronized修饰方法,而同步代码块主要是修饰需要进行同步的代码,用 synchronized(object){代码内容}进行修饰。

如何确保N个线程可以访问N个资源同时又不导致死锁?

使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。

线程状态?

创建、就绪、阻塞、运行、死亡

2.类、方法、注解相关

Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载O verloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写(Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被”屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。

接口和抽象类的区别是什么?

Java提供和支持创建抽象类和接口。它们的实现有共同点,不同点在于: • 接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。 • 类可以实现很多个接口,但是只能继承一个抽象类 • 类如果要实现一个接口,它必须要实现接口声明的所有方法。但是,类可以不实现抽象类声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。 • 抽象类可以在不提供接口方法实现的情况下实现接口。 • Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。 • Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。 • 接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。

JAVA反射获取类的三种方式

  1. 调用对象的.getClass()方法

  2. 调用某个类的.class属性

  3. 使用Class.forName+类的全路径

JAVA的四种标准元注解

@Target 修饰对象范围,例如types, packages @Retention 定义保留的时间长短,例如SOURCE,RUNTIME @Document描述javadoc @Inherited阐述某个被标注的类型是被继承的。作用:如果一个类用上了@Inherited修饰的注解,那么其子类也会继承这个注解。但是如果接口用上个@Inherited修饰的注解,其实现类不会继承这个注解;或者父类的方法用了@Inherited修饰的注解,子类也不会继承这个注解。这样操作后,子类可以获取父类的注解,字段等信息。

什么时候需要复写hashcode()和compartTo方法

HashMap中实现了一个Entry[]数组,数组的每个item是一个单向链表的结构,当我们put(key, value)的时候,HashMap首先会newItem.key.hashCode()作为该newItem在Entry[]中存储的下标,要是对应的下标的位置上没有任何item,则直接存储上去,要是已经有oldItem存储在了上面,那就会判断oldItem.key.equals(newItem.key),那么要是我们把上面的Person作为key进行存储的时候,重写了equals()方法,但没重写hashCode()方法,当我们去put()的时候,首先会通过hashCode() 计算下标,由于没有重写hashCode(),那么实质是完整的Object的hashCode(),会受到Object多个属性的影响,本来equals的两个Person对象,反而得到了两个不同的下标。 同样的,HashMap在get(key)的过程中,也是首先调用hashCode()计算item的下标,然后在对应下标的地方找,要是为null,就返回null,要是 != null,会去调用equals()方法,比较key是否一致,只有当key一致的时候,才会返回value,要是我们没有重写hashCode()方法,本来有的item,反而会找不到,返回null结果。 所以,要是你重写了equals()方法,而你的对象可能会放入到散列(HashMap,HashTable或HashSet等)中,那么还必须重写hashCode(), 如果你的对象有可能放到有序队列(实现了Comparable)中,那么还需要重写compareTo()的方法。

3.容器

HashMap和Hashtable有什么区别?

• HashMap和Hashtable都实现了Map接口,因此很多特性非常相似。但是,他们有以下不同点: • HashMap允许键和值是null,而Hashtable不允许键或者值是null。 • Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。 • HashMap提供了可供应用迭代的键的集合,因此,HashMap是快速失败的。另一方面,Hashtable提供了对键的列举(Enumeration)。 o 一般认为Hashtable是一个遗留的类。

数组(Array)和列表(ArrayList)有什么区别?什么时候应该使用Array而不是ArrayList?

• Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。 • Array大小是固定的,ArrayList的大小是动态变化的。 • ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。 • 对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。

ArrayList和LinkedList有什么区别?

ArrayList和LinkedList都实现了List接口,他们有以下的不同点: • ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素链表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。 • 相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。 • LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

HashSet和TreeSet有什么区别?

HashSet是由一个hash表来实现的,因此,它的元素是无序的。add(),remove(),contains()方法的时间复杂度是O(1)。 另一方面,TreeSet是由一个树形的结构来实现的,它里面的元素是有序的。因此,add(),remove(),contains()方法的时间复杂度是O(logn)。

说出ArrayList,Vector, LinkedList的存储性能和特性

List的子类特点 ArrayList: 底层数据结构是数组,查询快,增删慢 线程不安全,效率高 Vector: 底层数据结构是数组,查询快,增删慢 线程安全,效率低 LinkedList: 底层数据结构是链表,查询慢,增删快 线程不安全,效率高

String,StringBuffer,StringBuilder

String底层是final char value[]。因此其不可变。 StringBuffer和StringBuilder都是继承自AbstractStringBuilder,其底层使用的是char value[](无final),所以可变。StringBuffer是线程安全的(使用synchronized保证),StringBuilder不是。 每次对String类型进行改变时,会生成一个新的String对象,然后把指针指向新的String,但是其他两个都是操作自身。

4.javaWeb

RPC和http的区别

RPC:Remote Produce Call远程过程调用,类似的还有RMI(Remote Methods Invoke 远程方法调用,是JAVA中的概念,是JAVA十三大技术之一)。自定义数据格式,基于原生TCP通信,速度快,效率高。早期的webservice,现在热门的dubbo,都是RPC的典型

RPC的框架:webservie(cxf)、dubbo RMI的框架:hessian Http:http其实是一种网络传输协议,基于TCP,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用Http协议。也可以用来进行远程服务调用。缺点是消息封装臃肿。

现在热门的Rest风格,就可以通过http协议来实现。

http的实现技术:HttpClient 相同点:底层通讯都是基于socket,都可以实现远程调用,都可以实现服务调用服务

不同点: RPC:框架有:dubbo、cxf、(RMI远程方法调用)Hessian 当使用RPC框架实现服务间调用的时候,要求服务提供方和服务消费方 都必须使用统一的RPC框架,要么都dubbo,要么都cxf

跨操作系统在同一编程语言内使用 优势:调用快、处理快

http:框架有:httpClient 当使用http进行服务间调用的时候,无需关注服务提供方使用的编程语言,也无需关注服务消费方使用的编程语言,服务提供方只需要提供restful风格的接口,服务消费方,按照restful的原则,请求服务,即可

跨系统跨编程语言的远程调用框架 优势:通用性强

如何选择? 既然两种方式都可以实现远程调用,我们该如何选择呢?

速度来看,RPC要比http更快,虽然底层都是TCP,但是http协议的信息往往比较臃肿 难度来看,RPC实现较为复杂,http相对比较简单 灵活性来看,http更胜一筹,因为它不关心实现细节,跨平台、跨语言。 因此,两者都有不同的使用场景:

如果对效率要求更高,并且开发过程使用统一的技术栈,那么用RPC还是不错的。 如果需要更加灵活,跨语言、跨平台,显然http更合适 那么我们该怎么选择呢?

微服务,更加强调的是独立、自治、灵活。而RPC方式的限制较多,因此微服务框架中,一般都会采用基于Http的Rest风格服务。 (注:原文链接:HTTP与RPC的区别_谦虚使人发胖的博客-CSDN博客_http和rpc

cookie与session区别对比:

  • cookie数据存放在客户的浏览器上,session数据放在服务器上

  • cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session

  • session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE

  • 单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。

所以:将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中

JDBC过程

//加载数据库驱动(mysql其实不做这一步也可以,类会自动去注册驱动,但Oracle是必须要做的)
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库连接
Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?
characterEncoding=utf-8", "root", "root");                           
                            
//获取预处理对象statement                            
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//执行SQL
ResultSet resultSet = preparedStatement.executeQuery();
                            

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值