招银网络面试

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在这里插入图片描述

这里有一个非常特殊的注解@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();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值