1.float类型+double类型最后会转化成什么类型?double类型
float属于单精度浮点数据,只能提供7位有效数字
double属于双精度浮点数据,只能提供16位有效数字
所以double的精度要比float 要高。 double可以保存小数点后16位,float只能保存7位,所以float是可以自动转为 double,而float转double的时候会损失精度
还有 float 类型是 float32位 4字节
double类型是 64位8字节
天生注定了 只能是 float 可以 转为 double, double 不能转为float.
自动类型转换:
条件自动类型转换
必须满足转换前的数据类型的位数要低于转换后的数据类型,例如: short数据类型的位数为16位,就可以自动转换位数为32的int类型,同样float数据类型的位数为32,可以自动转换为64位的double类型。
2.char c = 97;
char d = (char) (c - 32);
System.out.println(d);
也是自动转化的问题。
3.hashcode与equals的问题:
每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!hashcode()主要是检查对象是不是在相同的数组位置,不在就肯定不相等了。
springboot的@springbootApplication
非常重要的三个类:
1.@SpringBootConfiguration
SpringBootConfiguration其实就是对spring的@Configuration进行了一次简单的封装,功能跟@Configuration差不多,就是把一个类标志成配置类,相当与spring的application.xml配置文件一样,等价于于配置文件中的,而@Bean等价于。
2.@ComponentScan
@ComponentScan主要是用来开启组件扫描,它扫描指定路径下的被@Component/@Controller等标注的类,并将其实例化后注入到IOC容器内,相当于配置文件中的标签。
Spring Boot引入自动配置,而这都是依赖于@EnableAutoConfiguration注释,这个注释会自动载入程序所需要的bean-依赖于Spring Boot在类路径中的查找。
3.@EnableAutoConfiguration![在这里插入图片描述](https://img-blog.csdnimg.cn/20201119161955916.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgyMzc1Ng==,size_16,color_FFFFFF,t_70#pic_center)
这里有一个非常特殊的注解@Import,即@Import(AutoConfigurationImportSelector.class)
@Import用来导入组件AutoConfigurationImportSelector它的作用就是给容器导入组件
里面有一个重要的方法selectImports()
它主要是通过调用SpringFactoriesLoader.loadFactoryNames()扫描所有jar包类路径, META-INF/spring.factories
把扫描到的这些文件的内容包装成properties对象
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器
中
每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置
从 ClassPath下扫描所有的 META-INF/spring.factories 配置文件,并将spring.factories文件中的 EnableAutoConfiguration对应的配置项通过反射机制实例化为对应标注了 @Configuration 的形式的IoC配置类,然后注入IoC容器。
spring中Bean的生命周期:
因为在spring中,spring只对单例的bean的生命周期进行管理,而对于prototype类型产生的bean则会直接交给用户,而不对其进行管理。
1.首先会对bean进行实例化,
2.然后对bean里对应的属性进行配置,也就是IOC注入
3.如果Bean实现了对应的Aware接口,则会去执行相应的重写的方法。
4.如果Bean关联了BeanPostProcessor接口,则会去执行postProcessorBeforeInitial()方法,BeanPostProcessor经常用来修改Bean内容。
5.如果Bean配置了init-method指定初始化方法,则就会去执行指定的初始化方法
6.如果Bean关联了BeanPostProcessor接口,则会去执行postProcessorafterInitial()方法。
这样我们就可以应用这个Bean了
7.不用了则会进行清理,如果Bean实现了disableBean方法,则会调用相应的destory()方法。
8.最后,如果这个Bean配置了destory-method方法,则就会去执行对应的方法。
Bean的作用域
主要有5个作用域:
1.singleton
Ioc只会创建一个Bean实例,每次获取的Bean都是同一个
2.prototype
Ioc可以创建多个实例bean,每次获取到的Bean都是新的Bean
3.request
该属性只会对HTTP请求产生作用,每一次HTTP请求就会创建一个新的Bean
4.session
该属性只用于HTTP session,同一个session共享同一个Bean,不同session使用不同的Bean
5.global-session
该属性只用于HTTP session,所有的session共享同一个Bean
Bean是线程安全的吗
结论:不是线程安全的
因为spring本来没有对Bean的线程安全策略,但是这个得根据对bean的作用域进行情况的判定。
对于prototype来说,每一次获取都是新的bean,所以多个线程拥有自己的bean,bean不是共享的,所以就不存在线程安全的问题,但是对spring来说,默认创建的bean是单例的,也就是多个线程共享同一个Bean,存在资源竞争,这样就可能产生线程安全了,但只是可能,不是绝对的,这个得对bean的状态进行判定。
如果这个Bean是无状态的,也就是线程不会对线程中的成员进行除了查以外的操作,那么这个Bean又是线程安全的了,比如controller 和service等,大多是无状态的,因为我们指关注方法的本身。
所以spring创建的bean大部分时间是无状态的,所以从某种程度上说他又是线程安全的。
因此无状态的单例是线程安全的。
如果bean里面有对属性字段进行操作的话,我们可以定义bean的定义域为prototype,但是只对非static变量起作用,因为static变量是属于类的,始终只有一份,那这样就只能通过ThreadLocal来封装解决变量的线程安全问题。
#{}与${}的区别
#{}是预编译处理,$ {}是字符串替换。
mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
mybatis在处理 $ { } 时,就是把 ${ } 替换成变量的值。
使用 #{} 可以有效的防止SQL注入,提高系统安全性。
因为#{}已经是经过预编译了 ,我们传进来的参数都会被当成是字符串,都会加上双引号,所以它不会改变sql语句。
而${}是字符替换,传递的参数会被当成sql的一部分,所以就改变了sql语句,这样就很容易导致sql注入从而变成了恶意执行的sql语句了
${}比如order by ${} 或者like 或 者 传 递 表 名 字 的 时 候 就 必 须 使 用 {} 或者传递表名字的时候就必须使用 或者传递表名字的时候就必须使用{}
什么是sql注入
SQL 注入能使攻击者绕过认证机制,完全控制远程服务器上的数据库
sql注入会对数据库的数据造成泄露等危险问题,sql注入只会对statement有效,而对prepareStatement是无效的,为什么呢?因为prepareStatement会对sql语句进行预编译,这样就不会因为参数的插入而导致sql语句的逻辑结构改变。
事务读已提交和可重复读的区别
@RequestMapping没有指定get和post,我们提交的时候springMvc是如何鉴别的?
一个sql执行很慢怎么优化
线程A 打印A 线程B打印B,交叉打印ABABAB10次
public class Test2{
boolean flag = true;
public synchronized void printA() throws InterruptedException {
if (flag == false){
this.wait();
}
System.out.print("A");
flag = false;
this.notifyAll();
}
public synchronized void printB() throws InterruptedException {
if (flag == true){
this.wait();
}
System.out.print("B");
flag = true;
this.notifyAll();
}
}
public class Test {
public static void main (String[] args) {
Test2 test2 = new Test2();
new Thread(new Runnable(){
@Override
public void run () {
for (int i = 0; i <= 10; i++){
try{
test2.printA();
}catch (Exception e){
e.getMessage();
}
}
}
}).start();
new Thread(new Runnable(){
@Override
public void run () {
for (int i = 0; i <= 10; i++){
try{
test2.printB();
}catch (Exception e){
e.getMessage();
}
}
}
}).start();
}
}