1、String类中常用的方法
split():把字符串分割成字符串数组
indexOf():从指定字符提取索引位置
trim():去除字符串两端空格
replace():替换
hashCode():返回此字符串的哈希码
subString():截取字符串
equals():比较
length():获取字符串的长度
valueOf():转换为字符串
concat():将指定字符串连接到此字符串的结尾
compareTo():用来比较两个字符串的字典顺序
compareToIgnoreCase():不考虑大小写,按字典顺序比较两个字符串
contains(): 检查一个字符串中是否包含想要查找的值
2、重载重写的区别
重载: 发生在同一个类中,方法名必须相同,参数类型不同,个数不同,顺序不同,与方法的修饰符和返回值无关
重写: 发生在父子类中,方法名.参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,
3、int、Integer自动拆箱、装箱介绍
装箱就是 自动将基本数据类型转换为包装类型;
拆箱就是 自动将包装类型转换为基本数据类型;
在定义变量的时候,比如Integer num = 1;就会自动装箱成Integer对象操作,int num2 = num;就会进行自动拆箱操作
在比较的时候,也会会发生拆箱和装箱操作
无论如何,Integer与new Integer不会相等。不会经历拆箱过程
两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false
两个都是new出来的,都为false
int和Integer或者new Integer比较,都为true,因为会把Integer自动拆箱为int再去比
1)Integer是int的包装类,int则是java的一种基本数据类型
(2)Integer变量必须实例化后才能使用,而int变量不需要
(3)Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
(4)Integer的默认值是null,int的默认值是0
(5)java在编译Integer i = 100 ;时,会翻译成为Integer i = Integer.valueOf(100)。而java API中对Integer类型的valueOf的定义如下,对于-128到127之间的数,会进行缓存,Integer i = 127时,会将127这个Integer对象进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了
1. package com.atguigu.interview.chapter03;
2.
3. /**
4. * @author atguigu
5. * @since 2019/7/28
6. */
7. public class Test01 {
8.
9. public static void main(String[] args){
10. Integer a = 127;
11. Integer b = 127;
12. Integer c = 128;
13. Integer d = 128;
14. System.out.println(a==b); //true
15. System.out.println(c==d); //false
16. }
17. }
4、值传递和引用传递
从这两个定义可以知道,就是这两种行为发生在传递的过程中
值传递呢就是传递的过程中,传递的是值,对值操作之后,不会影响原有变量的值
引用传递就是传递的过程中,传递的是引用,操作引用之后,会影响原有变量的值
在传递的过程中,如果传递的是基本数据类型以及String,那么都是值传递,不会改变原有变量
在传递的过程中,如果传递的是对象,如果修改了属性的值,那么会直接改动原有对象,会影响外面的值,如果没有修改对应的属性值,那么原有对象不受任何影响。
5、==和equal的区别
==的话它的作用是判断两个对象的地址是不是相等。就是判断两个对象是不是同一个对象。但是如果有基本数据类型参与比较,无论是基本数据类型相互比较,还是基本数据和他们的封装类比较,都比较的是值,
引用数据类型之间比较的是内存地址
equals的话 , 它的作用也是判断两个对象是否相等。但它一般有两种使用情况,一种呢是这个类没有重写equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
另一种呢就是类重写了 equals() 方法,重写了之后就按照重写的逻辑来判断了。一般,我们都覆盖 equals() 方法来比较两个对象的内容相等; 若它们的内容相等,就认为两个对象是相等的。
6、String 和 StringBuffer,StringBuilder 的区别是什么
从可变性来说呢,String底层呢其实就是个char数组,使用final修饰了,所以是不可变的,StringBuilder 与 StringBuffer是可变的字符串
从安全上来说,String 中的对象是不可变的,也就可以理解为常量,线程安全。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是不线程安全的。
从性能上来说,每次对 String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的String 对象。StringBuffer 每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。StirngBuilder的效率会高一些,而StringBuffer的底层加了同步的关键字,性能会有所下降
所以呢,一般我们操作少量的字符串的时候用String ,在单线程环境下操作大量数据时使用StringBuilder,在多线程操作大量数据使用StringBuffer
7、final、finally、finalize的区别
Final是一个安全修饰符,就是用final修饰的类不能被继承,用final声明的方法不能被重写,使用final声明的变量就相当于常量,不能被修改。
Finally是在异常里经常用到的,就是try和cach里的代码执行完以后,必须要执行的方法,我们经常在finally里写一些关闭资源的方法,关闭IO流什么的,就算是try和catch里有return代码,也会执行finally里的内容的,除非在try catch里遇到System.exit代码,整个主线程就停掉了,才不会执行finally里的代码
Finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以被垃圾回收
8、接口和抽象类的区别
接口的方法默认是 public,所有方法在接口中不能有实现,不过在Java 8 开始接口方法可以有默认实现,抽象类可以有非抽象的方法
接口中的实例变量默认是 final 类型的,而抽象类中则不一定
一个类可以实现多个接口,但最多只能实现一个抽象类
一个类实现接口的话要实现接口的所有方法,而抽象类不一定
接口不能用 new 实例化,但可以声明,但是必须引用一个实现该接口的对象,从设计层面来 说,抽象是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
9、Java的基本数据类型
基本数据类型有8中,分别是byte、short、int、long、float、double、char、boolean,对应基本类型,都会有一个封装类
10、jdk1.8的新特性
这块的话,我先说一些我们项目中经常会用到的吧
首先呢就是lamda表达式这块,遍历集合以及定义匿名函数,简直是非常方便
还有就是switch中的变量可以是string类型了,之前只能是基本数据类型
还有就是stream流式编程,这个的话可以让我们用strem的方式可以非常方便的对集合里的数据操作
还有就是新的时间类,LocalDate、LocalTime、LocalDateTime这几个类,让我们操作日期的时候非常方便,既可以自定义日期,还可以对年月日时分秒随时进行加减,以及快速格式化和强转等
还有就是其他一些我从别人的博客里看到的,我做的这些项目中没遇到过,就像Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字就行了,给我的感觉就是,我们在接口里定义一些初始化方法很方便了,不用在每个实现类里都实现一遍了,也是非常方便的
11、你是怎样理解面向对象的
面向对象是利于语言对现实事物进行抽象。面向对象具有以下四大特征:
(1)继承:继承是从已有类得到继承信息创建新类的过程
(2)封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。
(3)多态性:多态性是指允许不同子类型的对象对同一消息作出不同的响应。
(4)抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。
12、介绍下反射
简单说,在 Java 中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法,并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能就是 Java 语言的反射机制。
在java 中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。反射的作用其实就是:在运行时能够判断任意一个对象所属的类, 还有就是在运行时构造任意一个类的对象,我们常用的Spring框架也是利用Java反射这一块架构的,还有就是在运行时判断任意一个类所具有的成员变量和方法,还能在在运行时调用任一对象的方法,还有在运行时创建新类对象
一般都是使用Class clazz=Class.forName(“类的全路径”)这个方法,获取到class,获取到了之后,可以获取到类中所有的method方法,和所有的属性,调用Method的invoke方法就可以执行该方法,但是如果是私有方法的话,必须通过getDeclaredMethod获取,还需要调用方法的setAccessible设置为true才可以执行。
13、说一下常见的异常
最常见的莫过于空指针NullPointException了,一般都是空对象调用他的方法了
还有就是FileNotFound异常了,在文件操作的时候,一不小心路径写错了,或者是windows切换linux的时候,因为路径格式不一致,经常会有这个错误
还有就是ClassCastException,类转换异常,这块从json中的数据转换成类的时候经常会出现
接着就是SQLException,非常熟悉的错误信息就是Unknown column xxx,这种错误的话,就是列名错了,还有就是 You have an error in your SQL syntax,check xxxx near xxx,这个错误就是sql语法错误,异常信息会指出来错误的具体地方,还有就是Result consisted of more than one row,这个的话发生在selectOne方法的时候,想要获取一个结果集,但是返回了好多个
14、Object中有哪些方法
(1)protected Object clone()—>创建并返回此对象的一个副本。
(2)boolean equals(Object obj)—>指示某个其他对象是否与此对象“相等”。
(3)protected void finalize()—>当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
(4)Class<? extendsObject> getClass()—>返回一个对象的运行时类。
(5)int hashCode()—>返回该对象的哈希码值。
(6)void notify()—>唤醒在此对象监视器上等待的单个线程。
(7)void notifyAll()—>唤醒在此对象监视器上等待的所有线程。
(8)String toString()—>返回该对象的字符串表示。
(9)void wait()—>导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
void wait(long timeout)—>导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll()方法,或者超过指定的时间量。
void wait(long timeout, int nanos)—>导致当前的线程等待,直到其他线程调用此对象的 notify()
15、什么是Java序列化,如何实现Java序列化
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
序 列 化 的 实 现 : 将 需 要 被 序 列 化 的 类 实 现 Serializable 接 口 , 该 接 口 没 有 需 要 实 现 的 方 法 , implements Serializable 只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用 ObjectOutputStream 对象的 writeObject(Object obj)方法就可以将参数为 obj 的对象写出(即保存其状态),要恢复的话则用输入流。
常见应用场景:
对象在进行网络传输(比如远程方法调用 RPC 的时候)之前需要先被序列化,接收到序列化的对象之后需要再进行反序列化;
将对象存储到文件之前需要进行序列化,将对象从文件中读取出来需要进行反序列化;
将对象存储到数据库(如 Redis)之前需要用到序列化,将对象从缓存数据库中读取出来需要反序列化;
将对象存储到内存之前需要进行序列化,从内存中读取出来之后需要进行反序列化。