Java 面试分享《二》
一、Java 的八大基本数据类型以及它们的默认值,包装类
- 1.数据类型:byte,short,int,long,float,double,char,boolean
- 2.默认值:0,0,0,0L,0.0f,0.0d,null,false
- 3.包装类:Byte,Short,Integer,Long,Float,Double,Character,Boolean
二、String,StringBuilder 和 StringBuffer 的区别
- 1.String:字符串常量,用来创建和操作字符串
- 2.StringBuilder,StringBuffer:字符串变量,用来对字符串进行修改
- 3.区别:
3.1 String 表示不可变字符序列,是只读字符串,所引用的字符串不能被改变
3.2 StringBuilder 和 StringBuffer 实现方法类似,表示可变字符序列
3.3 StringBuilder 是线程不安全的,StringBuffer 是线程安全的
3.4 StringBuilder 执行速度快,效率高;StringBuffer 执行速度慢,效率低
- 4.总结:
4.1 如果要操作少量的数据用 String
4.2 多线程操作字符串缓冲区下操作大量数据 StringBuffer
4.3 单线程操作字符串缓冲区下操作大量数据 StringBuilder
三、Java 代码实现鸡兔同笼
public static void main(String[] args) {
int j = 0;
for (int i = 0; i <= 35; i++) {
j = 35 - i;
if (2 * i + 4 * j == 94) {
System.out.println("鸡的个数是:" + i);
System.out.println("兔的个数是:" + j);
}
}
}
四、MySQL 数据库的主键,外键,索引,唯一索引的含义和关系
- 1.主键(primary key):能够唯一标识表中某一行的属性或属性组。一个表只能有一个主键,但可以有多个候选索引。主键常常与外键构成参照完整性约束,防止出现数据不一致。主键可以保证记录的唯一和主键域非空,数据库管理系统对于主键自动生成唯一索引,所以主键也是一个特殊的索引。
- 2.外键(foreign key):是用于建立和加强两个表数据之间的链接的一列或多列。外键约束主要用来维护两个表之间数据的一致性。简言之,表的外键就是另一表的主键,外键将两表联系起来。一般情况下,要删除一张表中的主键必须首先要确保其它表中的没有相同外键(即该表中的主键没有一个外键和它相关联)。
- 3.索引(index):是用来快速地寻找那些具有特定值的记录。主要是为了检索的方便,是为了加快访问速度, 按一定的规则创建的,一般起到排序作用。
- 4.唯一性索引:这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。
- 5.关系:
5.1 主键一定是唯一性索引,唯一性索引并不一定就是主键
5.2 一个表中可以有多个唯一性索引,但只能有一个主键
5.3 主键列不允许空值,而唯一性索引列允许空值
5.4 主键可以被其他字段作外键引用,而索引不能作为外键引用
五、将成绩表 A 中各分数段的人数写入到 B 表(一条 sql 语句实现)
select sum(case when score between 90 and 100 then 1 else 0 end) as "优秀",
sum(case when score between 75 and 89 then 1 else 0 end) as "良好",
sum(case when score between 60 and 74 then 1 else 0 end) as "及格",
sum(case when score<60 then 1 else 0 end) as "不及格"
from A;
六、爬楼梯问题(一次可以走一阶,二阶或者三阶楼梯,n 阶楼梯有多少种走法)
//递归调用
public static int countNumber(int n) {
int sum = 0;
if (n == 0) {
return 0;
}
if (n == 1) {
return 1;
} else if (n == 2) {
return 2;
} else if (n == 3) {
return 4;
} else if (n > 3) {
return countNumber(n - 3) + countNumber(n - 2)
+ countNumber(n - 1);
}
return sum;
}
七、Spring 常用注解以及它们的含义
- 1.@Configuration:等价 与 XML 中配置 beans,相当于 Ioc 容器,它的某个方法头上如果注册了 @Bean,就会作为这个 Spring 容器中的 Bean,与 xml 中配置的 bean 意思一样。
- 2.@Autowired:它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。 通过 @Autowired 的使用来消除 set ,get 方法,简化 xml 中 bean 的配置。
- 3.@Resource:默认按 byName 自动注入,如果找不到再按byType找 bean,如果还是找不到则抛异常,无论按 byName 还是 byType 如果找到多个,则抛异常。可以手动指定 bean,它有2个属性分别是 name 和 type ,使用 name 属性,则使用 byName 的自动注入,而使用 type 属性时则使用 byType 自动注入,在程序里使用@Resource:@Resource(name=“bean名字”) 或 @Resource(type=“bean的class”)。
- 4.@Value:使用 @Value 可以简单的从 properties 配置文件里取配置,在程序里使用@Value:@Value("${wx_appid}")。
- 5.@Controller:使用它标记的类就是一个SpringMVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法。通俗来说,被 Controller 标记的类就是一个控制器,这个类中的方法,就是相应的动作。
- 6.@Service:用于标注业务层组件,被标注的类将自动实例化注册到 Spring 容器。
- 7.@Repository:用来表示持久层,注解可以标记在任何的类上,用来表明该类是用来执行与数据库相关的操作,并支持自动处理数据库操作产生的异常。
- 8.@Component:描述 Spring 中的 Bean,泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
- 9.@RequestMapping:是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
- 10.@ResponseBody:作用是将 controller 的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到 response 对象的 body 区,通常用来返回 JSON 数据或者是 XML。
- 11.@PathVariable: 可以将 URL 中占位符参数绑定到控制器处理方法的入参中。
- 12.@RequestParam:可以将 URL 中的参数绑定到处理函数方法的变量中 。
- 13.@RestController:@RestController = @Controller + @ResponseBody,是2个注解的合并效果,即指定了该 controller 是组件,又指定方法返回的是 String 或 json 类型数据。
八、Spring 事务的传播行为和隔离级别
事务注解方式: @Transactional
【一】传播行为:使用方法:@Transactional(propagation=Propagation.REQUIRED)
- 1.Require:支持当前事务,如果没有事务,就建一个新的,这是最常见的。
- 2.Supports:支持当前事务,如果当前没有事务,就以非事务方式执行。
- 3.Mandatory:支持当前事务,如果当前没有事务,就抛出异常。
- 4.RequiresNew:新建事务,如果当前存在事务,把当前事务挂起,先执行新的在执行旧的。
- 5.NotSupported:容器不为这个方法开启事务。
- 6.Never:以非事务方式执行,如果当前存在事务,则抛出异常。
- 7.Nested:新建事务,如果当前存在事务,把当前事务挂起。与 RequireNew 的区别是与父事务相关,且有一个 savepoint。
【二】隔离级别:为了使性能与数据的有效性之间达到平衡,不是级别越高越好,合适才是最好的。多用于处理多事务的并发问题,并行可以提高数据库的吞吐量和效率。使用方法:@Transactional(isolation = Isolation.SERIALIZABLE)
- 1.Read Uncommitted:读取未提交数据。
- 2.Read Committed:读取已提交数据。大多数主流数据库的默认事务等级。
- 3.Repeatable Read:可重复读。
- 4.Serializable:串行化。最严格的级别,事务串行执行,资源消耗最大。
- 5.相关概念:
5.1 脏读 : 一个事务读取到另一事务未提交的更新数据
5.2 不可重复读 : 在同一事务中,,多次读取同一数据返回的结果有所不同,即后续读取可以读到另一事务已提交的更新数据
5.3 可重复读:在同一事务中多次读取数据时,能够保证所读数据一样,即后续读取不能读到另一事务已提交的更新数据
5.4 幻读 : 一个事务读到另一个事务已提交的 nsert 数据
- 6.附图:
九、#{} 和 ${} 的区别
- 1.#{}:#{} 是将传入的值当做字符串的形式,例如:select id,name,age from student where id =#{id},当前端把 id 值1,传入到后台的时候,就相当于 select id,name,age from student where id =‘1’。
- 2. : {}: :{} 是将传入的数据直接显示生成 sql 语句,例如:select id,name,age from student where id =${id},当前端把 id 值1,传入到后台的时候,就相当于 select id,name,age from student where id = 1。
- 3.使用 #{} 可以很大程度上防止 sql 注入(语句的拼接 #{xxx} 使用的是 PreparedStatement,会有类型转换,比较安全。简单的说就是 #{} 是经过预编译的,是安全的;${} 是未经过预编译的,仅仅是取变量的值,是非安全的,存在 SQL 注入)。
- 4.但是如果使用在 order by 中就需要使用 ${}。
- 5.在大多数情况下还是经常使用 #{},但在不同情况下必须使用 ${}。
十、Java 代码实现读取文件夹下所有的文件及子文件夹下的文件
package com.icitic.agilecms.test;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
public class TestGetFiles {
/**
* 获取一个文件夹下的所有文件全路径
* @param path
* @param listFileName
*/
public static void getAllFileName(String path,ArrayList<String> listFileName){
File file = new File(path);
File [] files = file.listFiles();
String [] names = file.list();
if(names != null){
String [] completNames = new String[names.length];
for(int i=0;i<names.length;i++){
completNames[i]=path+names[i];
}
listFileName.addAll(Arrays.asList(completNames));
}
for(File a:files){
if(a.isDirectory()){//如果文件夹下有子文件夹,获取子文件夹下的所有文件全路径。
getAllFileName(a.getAbsolutePath()+"\\",listFileName);
}
}
}
public static void main(String[] args){
ArrayList<String> listFileName = new ArrayList<String>();
getAllFileName("D:\\testfiles\\",listFileName);
for(String name:listFileName){
if(name.contains(".txt")||name.contains(".properties")){
System.out.println(name);
}
}
}
}