1. java的多态
多态的前提是 “继承 + 方法重写 + 父类引用指向子类对象”(即 父类 变量 = new 子类())。
向上转型是多态的基础,通过 “父类引用指向子类对象” 实现统一调用,牺牲了子类特有功能的直接访问,但换来了灵活性。
向下转型是向上转型的补充,用于在需要时 “恢复” 子类特有功能,但必须通过instanceof确保安全,否则会引发运行时异常。
编译看左边,运行看右边;
属性看左边,方法看右边。
- 字段访问是静态绑定:在编译时根据引用类型决定访问哪个字段
- 方法调用是动态绑定:在运行时根据实际对象类型决定调用哪个方法
public class Main {
public static void main(String[] args) {
Person person = new Son();
System.out.println(person.age); // 28
}
}
class Person{
int age = 28;
String name;
public Person(String name){
this.name = name;
}
}
class Son extends Person{
int age = 18;
public Son(){
super("name");
}
}
2. 重载与重写的区别
- 重载发生在一个类里面,方法名相同,参数列表不同(参数类型,个数、顺序不同),方法的返回值和修饰符可以不同,发生在编译时。
- 重写发生在父类与子类之间,方法名相同,参数列表相同,返回值的范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类,如果父类方法访问修饰符为private则子类不能重写该方法(因为都无法继承这个方法)
3. final关键字的作用
- final修饰的类不能被继承
- final修饰的方法不能被子类重写
- final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。但final修饰的对象中的属性可以修改,修饰的引用,所以只是对象的引用不能修改;
4. final 与 finally finalize()区别
final用于修饰类、方法和变量,finally用于异常处理中的清理操作,finalize用于对象被垃圾回收前的清理工作。
5. ==和equals的区别
== 对基本类型比 “值”,对引用类型比 “地址”;
equals 默认比 “地址”,重写后可比对象的 “内容”/"属性"。
比较对象内容时用 equals,比较是否为同一对象或基本类型值时用 ==。
注意: String 类重写了equals方法,使其逻辑变为:比较两个字符串的 “字符序列是否完全相同”。
equals方法主要用于判断两个字符串是否相等,如果a="abc" 比较b="abc"时等于true,因为常量池复用的原因。
而面对字面量“abc”是否等于new String(“abc”)时,== 因为判断的地址值,所以为false , 但 equals 为 true(String重写了equals)
// == 运算符比较基本类型,比较引用数据类型的内存地址(是否同一个对象)
// equals 方法 默认比较对象地址,重写后可比较对象内容 / 属性是否相等,常用于字符串的比较、自定义对象属性比较
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false(s1和s2指向堆中两个不同对象,地址不同)
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1.equals(s2)); // true(内容相同)
6. jvm jre jdk 三个的关系
- jdk >jre(java运行环境) > jvm(java虚拟机)
7. 单例设计模式
定义:确保一个类只有一个实例,并提供该实例的全局访问点。
好处:避免一个全局使用的类,频繁的创建与销毁,耗费系统资源。
单例模式设计要素,类似于封装
- 私有构造函数
- 私有静态变量
- 公有静态函数
- 饿汉式是在类加载就创建了对象实例,懒汉式是在使用才创建。
- 饿汉式不存在线程安全问题,懒汉式存在线程安全。
- 饿汉式存在浪费资源的可能,懒汉式不存在。
8. String 属于基础的数据类型吗? 字面量创建的字符串和new String创建的字符串有什么区别?
不是,引用数据类型,字面量创建之前会检查字符串常量池是否存在,如果存在就将常量池中的字符串对象引入复制给变量,不存在则创建一个新的字符串对象。
new 关键字会在堆内存中创建一个新的字符串对象,同时会检查字符串常量池,如果常量池不存在,会现在常量池中创建,并在堆中创建一个新对象并复制常量池中的内容。
如果常量池中已存在 "abc",则直接在堆中创建新对象并复制常量池中的内容。
9. java 中操作字符串都有哪些类?它们之间有什么区别?
String、StringBuffer、StringBuilder。
- String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象
- StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的区别在于,
StringBuffer 线程安全的, StringBuilder 非线程安全的
StringBuilder 的性能却高于 StringBuffer,
单线程环境下推荐使用 StringBuilder
多线程环境下推荐使用 StringBuffer。
10. session 和 cookie 有什么区别?
- 存储位置不同:session 存储在服务器端;cookie 存储在浏览器端。
- 安全性不同:cookie 安全性一般,在浏览器存储,可以被伪造和修改。
- 容量和个数限制:cookie 有容量限制,每个站点下的 cookie 也有个数限制。
- 存储的多样性:session 可以存储在 Redis 中、数据库中、应用程序中;而 cookie 只能存储在浏览器中。
11. tcp 和 udp的区别
tcp 数据传输慢,udp 数据传输快;
tcp 面向连接,udp 面向非连接即发送数据前不需要建立链接;
tcp 提供可靠的服务(数据传输),udp 无法保证;
tcp 面向字节流,udp 面向报文;
12. 抽象类必须要有抽象方法吗?
不需要,抽象类不一定非要有抽象方法。
当父类的一些方法不能确定时,可以用abstract关键字来修饰方法,这个方法就是抽象方法,用abstract来修饰该类就是抽象类
如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstracr类
- 抽象类能使用 final 修饰吗?
不能,final定义为不能继承
13. 介绍一下IO流
14. 线程的生命周期-状态
15 StringBuilder和StringBuffer的区别
- stringBuffer是线程安全的,方法中都加了synchronized
16 where 和 having的区别
- where执行在分组之前,having执行在分组之后。
17 mybatis中#{},${} 的区别
{}方式能够很大程度防止sql注入(安全),${}方式无法防止Sql注入
{}将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号
{},典型情况就是 动态参数(表名,参数名)