java面试(超级重点)

java的基础的东西一定学会

一. 基本数据类型

答:

1. 整型 byte(1字节) short (2个字节) int(4个字节) long (8个字节)

2.浮点型 float(4个字节) double(8个字节)

3.逻辑性 boolean(八分之一个字节)

4.字符型 char(2个字节,一个字符能存储下一个中文汉字)

二. String.StringBuffer.StringBuild的区别https://blog.csdn.net/rmn190/article/details/1492013

答:

String 字符串常量
StringBuffer 字符串变量(线程安全)
StringBuilder 字符串变量(非线程安全)

简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
 而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的:

三. JVM虚拟机的结构(jvm的优化)

 

虚拟机考点

 

四. 乐观锁 悲观锁

 

并发

 

乐观、悲观

1、CAS(Compare And Swap 比较并且替换)是乐观锁的一种实现方式,是一种轻量级锁,JUC 中很多工具类的实现就是基于 CAS 的。

举个栗子:现在一个线程要修改数据库的name,修改前我会先去数据库查name的值,发现name=“小王”,拿到值了,我们准备修改成name=“小明”,在修改之前我们判断一下,原来的name是不是等于“小王”,如果被其他线程修改就会发现name不等于“小王”,我们就不进行操作,如果原来的值还是小王,我们就把name修改为“小明”,至此,一个流程就结束了。

 

2、那开发过程中ABA你们是怎么保证的?

加标志位,例如搞个自增的字段,操作一次就自增加一,或者搞个时间戳,比较时间戳的值。

举个栗子:现在我们去要求操作数据库,根据CAS的原则我们本来只需要查询原本的值就好了,现在我们一同查出他的标志位版本字段vision。

线程和进程的理解

 

synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。

synchronized关键字最主要的三种使用方式:

修饰实例方法:作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁

修饰静态方法:因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象锁。

修饰代码块:指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁

总结: synchronized 关键字加到 static 静态方法和 synchronized(class)代码块上都是是给 Class 类上锁。synchronized 关键字加到实例方法上是给对象实例上锁。尽量不要使用 synchronized(String a) 因为JVM中,字符串常量池具有缓存功能!

 

乐观锁:

总是认为不会产生并发问题,每次去取数据的时候总认为不会有其他线程对数据进行修改,因此不会上锁,但是在更新时会判断其他线程在这之前有没有对数据进行修改,一般会使用版本号机制或CAS操作实现。

 version方式:一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。

核心SQL代码:

update table set x=x+1, version=version+1 where id=#{id} and version=#{version};  

CAS操作方式:即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试。

悲观锁:

 总是假设最坏的情况,每次取数据时都认为其他线程会修改,所以都会加锁(读锁、写锁、行锁等),当其他线程想要访问数据时,都需要阻塞挂起。可以依靠数据库实现,如行锁、读锁和写锁等,都是在操作之前加锁,在Java中,synchronized的思想也是悲观锁。

五. sql语句的优化https://blog.csdn.net/z719725611/article/details/52922695):

使用explain查看执行语句的效率

  1.不使用子查询

  SELECT * FROM t1 WHERE id (SELECT id FROM t2 WHERE name='hechunyang');

  但请注意的是:优化只针对SELECT有效,对UPDATE/DELETE子查询无效,固生产环境应避免使用子查询

  2.避免函数索引

  3.用IN来替换OR

  4.LIKE双百分号无法使用到索引

  5、读取适当的记录LIMIT M,N

  6、避免数据类型不一致

  7、分组统计可以禁止排序

  8、避免随机取记录

  9、禁止不必要的ORDER BY排序

  10、批量INSERT插入

六. synchronization和lock的区别https://blog.csdn.net/u012403290/article/details/64910926

类别synchronizedLock
存在层次Java的关键字,在jvm层面上是一个类
锁的释放1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁在finally中必须释放锁,不然容易造成线程死锁
锁的获取假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待分情况而定,Lock有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待
锁状态无法判断可以判断
锁类型可重入 不可中断 非公平可重入 可判断 可公平(两者皆可)
性能少量同步大量同步

七. http和https的区别https://blog.csdn.net/whatday/article/details/38147103

什么是 HTTPS?

HTTPS (基于安全套接字层的超文本传输协议 或者是 HTTP over SSL) 是一个 Netscape 开发的 Web 协议。

你也可以说:HTTPS = HTTP + SSL

HTTPS 在 HTTP 应用层的基础上使用安全套接字层作为子层。

 

八. int和Integer的区别https://blog.csdn.net/chenliguan/article/details/53888018

(1)Integer是int的包装类;int是基本数据类型;
(2)Integer变量必须实例化后才能使用;int变量不需要;
(3)Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;
(4)Integer的默认值是null;int的默认值是0。

 

九. 修改字段的sql语句

  添加字段:
  alter table 表名 add 字段名 类型
  删除字段:
  alter table 表名 drop column 字段名

  例子:alte table A add TEL_number char(10)

十. 集合

 

十一、什么是视图
视图(VIEW)也被称作虚表,即虚拟的表,是一组数据的逻辑表示,其本质是对应于一条SELECT语句,结果集被赋予一个名字,即视图名字。

视图本身并不包含任何数据,它只包含映射到基表的一个查询语句,当基表数据发生变化,视图数据也随之变化。

视图创建后,可以像操作表一样操作视图,主要是查询操作。 
语法中的Subquery是SELECT查询语句,对应的表被称作基表。 
根据视图所对应的子查询种类分为几种类型: 
•SELECT语句是基于单表建立的,且不包含任何函数运算、表达式或分组函数,叫做简单视图,此时视图是基表的子集;  
•SELECT语句同样是基于单表,但包含了单行函数、表达式、分组函数或GROUP BY子句,叫做复杂视图;  
•SELECT语句是基于多个表的,叫做连接视图。

2019/3/6

十二、如何解决js缓存的的问题,进行升级,新写的js没有效果

添加版本号,就进行解决了

 

十三、如何解决别人读的数据,别人进行了修改

常用的处理方法,就是进行乐观锁(添加版本字段),悲观锁比较影响效率。

 

 

十四、有大量的文件进行导入导出的解决方案

 

使用异步的导入导出。

 

十五、MyBatis 中的#和$的区别

#相当于对数据 加上 双引号,$相当于直接显示数据

  1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by “111”, 如果传入的值是id,则解析成的sql为order by “id”. 
  2. user_id$,如果传入的值是111,那么解析成sql时的值为order by user_id, 如果传入的值是id,则解析成的sql为order by id. 
  3. #方式能够很大程度防止sql注入。 
    4.方式无法防止Sql注入。5. 方式一般用于传入数据库对象,例如传入表名. 
    6.一般能用#的就别用$.

***
#{} 用于查询CRUD语句
${} 则用于模糊查询(记得加%%哦)
***

 

十六、redis使用的个数遵循2n+1的原则,一般答使用5个节点

 

十七、Tomcat/HTTP Server下如何获取客户端的真实ip地址

nginx下的配置对于nginx,我们可以通过一下配置:

proxy_set_header Host $host;

proxy_set_header X-Forwarded-For $remote_addr;

这样,在HTTP的header中就增加了一个X-Forwarded-For,这个保存着客户端的真实IP,然后在tomcat中通过以下方法:String host = httpServletRequest.getHeader("X-Forwarded-For");host = null == host ? httpServletRequest.getRemoteHost() : host;

 

十八、NIO、IO的区别(去理解内部原理)

老张爱喝茶,废话不说,煮开水。
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
1 老张把水壶放到火上,立等水开。(同步阻塞)
老张觉得自己有点傻
2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
3 老张把响水壶放到火上,立等水开。(异步阻塞)
老张觉得这样傻等意义不大
4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
老张觉得自己聪明了。

 

所谓同步异步,只是对于水壶而言。
普通水壶,同步;响水壶,异步。
虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。
同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。

所谓阻塞非阻塞,仅仅对于老张而言。
立等的老张,阻塞;看电视的老张,非阻塞。
情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。

 

十九、linux下查找文件

find:文件属性查找

grep:文件内容查找

https://www.cnblogs.com/zhangmo/p/3571735.html

 

 

二十、linux下打开任务管理器

top

https://blog.csdn.net/pan_tian/article/details/7734789

二十一、创建java的5种方式

二十二、ASCII、IOS、GBK、UTF-8的由来

二十三、自动装箱和自动拆箱

二十四、jsp的域

JSP页面四大域对象:

pageContext(当前页面有效)、 

request(当前请求有效)、 

session(当前会话有效)、

application(当前网站或当前Web应用)。

二十五、线程的实现方法

  • 继承Thread类
  • 实现Runnable接口、
  • 实现Callable接口通过FutureTask包装器来创建Thread线程、
  • 使用ExecutorService、Callable、Future实现有返回结果的多线程。

二十六、分布式与微服务的区别

  微服务:分散能力。

这里不引用书本上的复杂概论了,简单来说微服务就是很小的服务,小到一个服务只对应一个单一的功能,只做一件事。这个服务可以单独部署运行,服务之间可以通过RPC来相互交互,每个微服务都是由独立的小团队开发,测试,部署,上线,负责它的整个生命周期。

      分布式:分散压力。

分布式服务顾名思义服务是分散部署在不同的机器上的,一个服务可能负责几个功能,是一种面向SOA架构的,服务之间也是通过rpc来交互或者是webservice来交互的。逻辑架构设计完后就该做物理架构设计,系统应用部署在超过一台服务器或虚拟机上,且各分开部署的部分彼此通过各种通讯协议交互信息,就可算作分布式部署,生产环境下的微服务肯定是分布式部署的,分布式部署的应用不一定是微服务架构的,比如集群部署,它是把相同应用复制到不同服务器上,但是逻辑功能上还是单体应用。
 

二十七、activiti如何实现暂停启动操作

 

二十八、spring的2大特性

https://blog.csdn.net/gloomy_114/article/details/68946881?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

ioc(控制反转)和di(依赖注入)的区别

https://blog.csdn.net/qq_42709262/article/details/81951402?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

二十九、主从怎么搭建,哨兵模式怎么搭建

 

三十、锁表了怎么解决

1、查进程,主要是查找被锁表的那个进程的ID

SHOW PROCESSLIST;

2、kill掉锁表的进程ID

KILL   10866;//后面的数字即时进程的ID

 

三十一、String 类的常用方法: 

  • equals:字符串是否相同
  • equalsIgnoreCase:忽略大小写后字符串是否相同
  • compareTo:根据字符串中每个字符的Unicode编码进行比较
  • compareToIgnoreCase:根据字符串中每个字符的Unicode编码进行忽略大小写比较
  • indexOf:目标字符或字符串在源字符串中位置下标
  • lastIndexOf:目标字符或字符串在源字符串中最后一次出现的位置下标
  • valueOf:其他类型转字符串
  • charAt:获取指定下标位置的字符
  • codePointAt:指定下标的字符的Unicode编码
  • concat:追加字符串到当前字符串
  • isEmpty:字符串长度是否为0
  • contains:是否包含目标字符串
  • startsWith:是否以目标字符串开头
  • endsWith:是否以目标字符串结束
  • format:格式化字符串
  • getBytes:获取字符串的字节数组
  • getChars:获取字符串的指定长度字符数组
  • toCharArray:获取字符串的字符数组
  • join:以某字符串,连接某字符串数组
  • length:字符串字符数
  • matches:字符串是否匹配正则表达式
  • replace:字符串替换
  • replaceAll:带正则字符串替换
  • replaceFirst:替换第一个出现的目标字符串
  • split:以某正则表达式分割字符串
  • substring:截取字符串
  • toLowerCase:字符串转小写
  • toUpperCase:字符串转大写
  • trim:去字符串首尾空格

三十二、hashmap的遍历方式

我截取了部分源码,从这里可以看出,系统默认的负载因子值就是0.75,而且我们还可以在构造方法中去指定。下面我们就正式来分析一下为什么是默认的0.75。

 Initial Capacity与Load Factor

Initial Capacity:初始化容量,它表示HashMap底层的那个数组,也就是Entry数组有多长,这个值默认是16。Load Factor:负载因子,它表示HashMap的负载程度,换句话说,它表示HashMap到底有多满了,是不是需要扩容了,这个值默认是0.75f。初始化容量和负载因子的默认值是Java官方经过实践和优化得到的数据,可以适应大多数的场景。

当然也可以不使用其默认值,可以在构造的时候,自定义HashMap的容量和负载因子:

//单纯指定容量Map<String,String> hashMapWithCapacity=newHashMap<>(64)//自定义容量和负载因子Map<String,String> hashMapWithCapacityAndLF=newHashMap<>(64,0.9f)

一旦需要自定义容量和负载因子,我们需要搞清楚,他们到底是什么,用来干嘛,会对性能造成什么影响。

有如下几种方法:

1. 通过keyset

2. 通过 Map.entrySet().iterator()

3. 通过foreach ---- Map.entryset, 当hashmap很大时,推荐使用这种方式。

4. 通过Valueset

public static void main(String[] args) {
        HashMap<Integer, String> hashmap = new HashMap<>();
        hashmap.put(1,"gogo");
        hashmap.put(2,"wade");
        hashmap.put(3,"james");
        hashmap.put(4,"curry");
        // 1. 通过Map.keySet遍历key和value:
        for (int key : hashmap.keySet()){
            System.out.println("key: "+ key + "; value: " + hashmap.get(key));
        }
 
        //2. 通过Map.entrySet使用iterator遍历key和value:
        Iterator<Map.Entry<Integer, String>> it = hashmap.entrySet().iterator();
        while (it.hasNext()){
            Map.Entry<Integer, String> entry = it.next();
            System.out.println("key: "+ entry.getKey() + "; value: " + entry.getValue());
        }
 
        //3. 通过Map.entrySet遍历key和value
        for(Map.Entry<Integer, String> entry : hashmap.entrySet()){
            System.out.println("key: "+ entry.getKey() + "; value: " + entry.getValue());
        }
 
        //4. 通过Map.values()遍历所有的value,但不能遍历key
        for (String value : hashmap.values()) {
            System.out.println("value: "+value);
        }
    }

三十三、mysql的优化

 

三十四、

order by 字段 asc/desc

 

Linux查看进程命令

ps命令

-a,查看所有

-u,以用户(user)的格式显示

-x, 显示后台进程运行参数

 

ps 和 top 命令常用来查看Linux系统进程相关信息。

ps命令:可以查看进程的瞬间信息。

top命令:可以持续的监视进程的信息。

 

三十五、通过jquery获取下面的值【val() 方法

$("button").click(function(){
  $(":text").val("Hello World");
});

 

三十六、两种持久化方式

  redis提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Apend Only File)

   AOF:记录服务器每次写的操作,当服务器重启时会执行命令来恢复原来的数据(文件存储方式)

  RDB:在指定的时间间隔对数据进行快照存储(快照存储方式)

三十七、rabbitMQ的几种模式

这里简单介绍下六种工作模式的主要特点:

简单模式:一个生产者,一个消费者

work模式:一个生产者,多个消费者,每个消费者获取到的消息唯一。

订阅模式:一个生产者发送的消息会被多个消费者获取。

路由模式:发送消息到交换机并且要指定路由key ,消费者将队列绑定到交换机时需要指定路由key

topic模式:将路由键和某模式进行匹配,此时队列需要绑定在一个模式上,“#”匹配一个词或多个词,“*”只匹配一个词。

 

三十八:什么是线程安全

线程安全

“线程安全”也不是指线程的安全,而是指内存的安全。为什么如此说呢?这和操作系统有关。

假如现在A线程来执行这个方法,这些变量会在A的栈内存分配。与此同时,B线程也来执行这个方法,这些变量也会在B的栈内存中分配。

也就是说这些局部变量会在每个线程的栈内存中都分配一份。由于线程的栈内存只能自己访问,所以栈内存中的变量只属于自己,其它线程根本就不知道。

 

现实中往往会有一个变量需要多个方法都能够使用的情况,此时定义这个变量的“位置”就不能在方法里面了,而应该在方法外面。即从(方法的)局部变量变为(类的)成员变量,其实就是“位置”发生了变化。

类的成员变量不能再分配在线程的栈内存中,而应该分配在公共的堆内存中。其实也就是变量在内存中的“位置”发生了变化,由一个私有区域来到了公共区域。因此潜在的安全风险也随之而来。

要让公共区域堆内存中的数据对于每个线程都是安全的,那就每个线程都拷贝它一份,每个线程只处理自己的这一份拷贝而不去影响别的线程的,这不就安全了嘛。相信你已经猜到了,我要表达的就是ThreadLocal类了。

ThreadLocal就是,把一个数据复制N份,每个线程认领一份,各玩各的,互不影响。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值