找工作时,被问及专业相关问题,当然基本上也是基础类问题,被问到了还是要记录下来
1、mysql中 # 和 $ 有何区别?(在项目开发中用 #{} 比较多,为什么呢)
- #{} 表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,传入的数据都当成一个字符串,会对自动传入的数据加一个双引号
例如:
select * from table where name=#{name}
针对这个简单的查询语句,若传入的值为 张三,则解析成的sql就是这样的:
select * from table where name="张三"
- #{} 可以有效的防止sql注入
- ${} 表示拼接sql串,通过${}可以将parameterType传入的内容拼接在sql中且不进行jdbc类型转换
如上面的查询语句,用 name=${name},那么sql在解析的时候值为name=name,执行时就会报错
- ${} 方式无法防止sql注入,如验证用户名时通过 name=${abc or 1=1} 就可以实现sql注入的目的
- ${} 一般用于传入数据库对象,比如数据库表名
延伸:mybatis排序时,使用order by动态参数时需要注意,使用${} 而不用 #{}
2、spring和springBuffer及springBuilder区别?
- String
String对象是不可变的。String类中每一个看起来会修改String值的方法(如upcase等),实际上都是创建了一个全新的String对象,以包含修改后的字符串内容,而最初的String对象丝毫未动
特殊点注意:
String中的“+”和“+=”是java中仅有的两个重载过的操作符,它在字符串相加的时候有特殊意义,例:
String heart = "I" + "LOVE" + "YOU";
这段代码是如何工作的呢?
根据我们说String对象是不可变的,是不是应该这样:
String创建了一个新的对象来接收“I”和“LOVE”组合起来的新字符串,然后在创个对象来接受“ILOVE”和"YOU"组成的对象。
分析:
可如果是这样的话,就会产生一堆需要GC(垃圾回收)的对象,这样的话性能肯定相当糟糕。可是呢,它并不是像上面那样子的
实际上:
当你使用“+”连接字符串的时候,编译器会自动引入 java.lang.StringBuilder 类。虽然我们在源码中并没有使用StringBuilder类,但编译器去自作主张的使用了它,因为它更加高效。编译器会创建一个StringBuilder对象,并为每个字符串调用一次append()方法,而StringBuilder是可变的,因此它在这个过程中只创建了一个对象。
再看看这段代码:
String you="you"; String me="me"; for(int i=0;i<5;i++){ me += you; }
是不是每次循环都会创建一个StringBuilder对象。所以说,如果字符串操作简单,那就可以信赖编译器优化,但如果是在循环中,那最好自己创建一个StringBuilder对象,用StringBuilder的append等方法去操作会方便些。
- StringBuilder
StringBuilder是可变的,它不是线程安全的
- StringBuffer
StringBuffer是可变的,它是线程安全的,所以它的开销比StringBuilder大
注:一般这三个选用的顺序是: StringBuilder > StringBuffer > String
3、重载overload和重写override区别?
- 重载overload
表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)
应用场景:当方法功能相似,但需要传递不同的参数
- 重写override
表示子类中的方法可以与父类中的某个方法的名称和参数完全相同;
通过子类创建的实例对象调用这个方法时,将调用子类中的定义方法,这相当于把父类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现;
子类覆盖父类方法时,只能比父类中抛出更少的异常,或者是抛出父类抛出异常的子异常,因为子类可以解决父类的一些问题,不能比父类有更多的问题;
子类方法的访问权限只能比父类更大,不能更小。如果父类的方法是private类型,那么子类则不存在覆盖的限制,相当于子类中增加了一个全新的方法。
应用场景:子类有自己特有的行为,从父类继承而不能满足自身需要时。
注:重载和重写都是多态的表现,前者是编译器的多态,后者是运行期多态