问:JDK 和 JRE 有什么区别?
答:
jdk和jre的区别为:JRE是java运行时环境而JDK是java开发工具包,JDK包含JRE,但是JRE可以独立安装。
JDK:java development kit (java开发工具),JDK 是用于开发 Java 程序的最小环境。
JRE:java runtime environment (java运行时环境),是提供给 Java 程序运行的最小环境。
JRE包含了java虚拟机、java基础类库。是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的。JDK是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。运行java程序只需安装JRE。如果需要编写java程序,需要安装JDK。
问:== 和 equals 的区别是什么?
答:
一、对象类型不同
1、equals():是超类Object中的方法。
2、==:是操作符。
二、比较的对象不同
1、equals():用来检测两个对象是否相等,即两个对象的内容是否相等。
2、==:用于比较引用和比较基本数据类型时具有不同的功能,具体如下:
(1)、基础数据类型:比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样。
(2)、引用数据类型:比较的是引用的地址是否相同,比如说新建了两个User对象,比较的是两个User的地址是否一样。
三、运行速度不同
1、equals():没有==运行速度快。
2、==:运行速度比equals()快,因为==只是比较引用。
问:两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
答:
不对,两个对象的 hashCode()相同,equals()不一定 true。
代码示例:
String str1 = "通话";
String str2 = "重地";
System.out.println(String.format("str1:%d | str2:%d", str1.hashCode(),str2.hashCode()));
System.out.println(str1.equals(str2));
执行的结果:
str1:1179395 | str2:1179395
false
代码解读:很显然“通话”和“重地”的 hashCode() 相同,然而 equals() 却为 false
问:final 在 java 中有什么作用?
答:
在java中,final可以用来修饰类、方法和变量。final修饰类,表示该类是无法被任何其他类继承的,意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。final修饰类中的方法,表示该类是无法被任何其他类继承的,不可以被重写;也就是把该方法锁定了,以防止继承类对其进行更改。final修饰类中的变量,表示该变量一旦被初始化便不可改变。
问: String 属于基础的数据类型吗?
答:
不属于
“String 不属于基础类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。”
问: java 中操作字符串都有哪些类?它们之间有什么区别?
答:
String:对字符串不进行重复操作时选择用String。
StringBuilder:在单线程中对字符串进行重复操作时选择用StringBuilder。
StringBuffer:在多线程中对字符串进行重复操作时选择用StringBuffer。
问:String str="i"与 String str=new String(“i”)一样吗?
答:
结论不一样,使用String str="i",java虚拟机会把它分配到常量池中,而 String str=new String(“i”)创建了一个对象,会被分到堆内存中。
Java为了避免产生大量的String对象,设计了一个字符串常量池。工作原理是这样的,创建一个字符串时,JVM首先为检查字符串常量池中是否有值相等的字符串,如果有,则不再创建,直接返回该字符串的引用地址,若没有,则创建,然后放到字符串常量池中,并返回新创建的字符串的引用地址。所以,当你创建一使用String str="i"创建一个字符串时,str指向的是常量池中的这个字段。String str=new String(“i”)使用的是标准的对象创建方式 一个对象创建时,在虚拟机中的执行过程如下:
Object obj = new Object()
Object obj会反映到java虚拟机栈的变量表中,作为一个引用类型数据出现,“new Object()”会反映到java堆中,在java堆上创建一个Object类型的实例数据值的结构化内存,这块内存的长度是不固定的。在java堆中还存放了了能查到此对象类型数据(对象类型、父类、接口、方法等)的地址信息,这些信息存放在方法区中。
问:如何将字符串反转?
答:
1、利用字符串的拼接(charAt()方法),把后遍历出来的放在前面即可实现反转
2、利用字符串的拼接(toCharArray()处理成字符数组的方法),把后遍历出来的放在前面即可实现反转
3、利用StringBuffer的reverse()方法
问:String 类的常用方法都有那些?
答:
length()方法 获取字符串长度
charAt(int index)方法 传递一个下标参数,返回字符串对应位置的字符
indexOf()方法 传递某个字符,返回在字符串中的第一个位置
subString(int start)方法 默认是取到字符串末尾
subString(int start,int end)方法 注:范围左闭右开,不包含下标为end的那位
String判断功能
1)equals(Object obj):比较字符串的内容是否相同
2)equalsIgnoreCase(String anotherString):比较字符串的内容是否相同,忽略大小写
3)startsWith(String prefix):判断字符串对象是否以指定的字符开头(区分大小写)
4)startsWith(String prefix,int toffset):判断字符串对象是否以指定的字符开头,参数toffset为指定从哪个下标开始
5)endsWith(String str):判断字符串对象是否以指定的字符结尾
6)isEmpty():判断指定字符串是否为空
6)compareTo(String anotherString):比较字符串的大小,前者大返回整数,后者大返回负数,相等返回0
4.String类中的转化方法:
1)toCharArray():把字符串转换为字符数组
2)toLowerCase():把字符串转换为小写字符串
3)toUpperCase():把字符串转换为大写字符串
5.其他常用方法
1)trim():去除字符串两端空格
2)split():去除字符串中指定的的字符,然后返回一个新的字符串
3)subSequence(int beginIndex,int endIndex ):截取字符串中指定位置的字符组成一个新的字符串
4)replace(char oldChar, char newChar):将指定字符替换成另一个指定的字符
5)replaceAll(String regex,String replasement):用新的内容替换全部旧内容
6)replaceFirst(String regex,String replacement):替换首个满足条件的内容
7)lastIndexOf(String str):返回指定字符出现的最后一次的下标
8)contains(CharSequence s):查看字符串中是都含有指定字符
9)concat(String str):在原有的字符串的基础上加上指定字符串
问:抽象类必须要有抽象方法吗?
答:
不一定
抽象类不一定需要抽象方法,但一个类拥有抽象方法,那么这个类必须是抽象类,子类必须实现父类的抽象方法,或者子类本身也为抽象类,抽象类绝对不能用来初始化对象。
抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
问:普通类和抽象类有哪些区别?
答:
1、抽象类的存在时为了被继承,不能实例化,而普通类存在是为了实例化一个对象
2、抽象类的子类必须重写抽象类中的抽象方法,而普通类可以选择重写父类的方法,也可以直接调用父类的方法
3、抽象类必须用abstract来修饰,普通类则不用
4、普通类和抽象类都可以含有普通成员属性和普通方法
5、普通类和抽象类都可以继承别的类或者被别的类继承
6、普通类和抽象类的属性和方法都可以通过子类对象来调用
问:抽象类能使用 final 修饰吗?
不能
“不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类”
问:接口和抽象类有什么区别?
答:
问:java 中 IO 流分为几种?
答:
1. 字节流(Byte Stream):字节流操作单个字节,数据以字节为单位传输,适用于处理二进制数据和文本文件等境况。字节流有输入流(InputStream)和输出流(OutputStream)两种类型。
2. 字符流(Char Stream):字符流操作以字符为单位,处理文本和字符串数据,便于直接读取和输出字符串和文本文件等。字符流有输入流(Reader)和输出流(Writer)两种类型。
3. 缓冲流(Buffered Stream):缓冲流通过在底层流上添加带有缓冲区的包装器,以提高程序的IO性能。它可以减少IO操作的次数,从而更快地读写数据。
4. 对象流(Object Stream):对象流用于在对象之间传递非基本类型的数据,并且可以实现对象的持久化。它使用字节流来处理数据,但是只能将实现了 Serializable 接口的对象写入流中。
问: BIO、NIO、AIO 有什么区别?
答:
JAVA BIO:同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程并处理,如果这个连接不做任何事情会造成不必要的开销,当然可以通过线程池机制改善
JAVA NIO:同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时才启动一个线程进行处理
JAVA AIO(NIO2):异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理;
2.使用场景
BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。
3.BIO 同步并阻塞
tomcat采用的传统的BIO(同步阻塞IO模型)+线程池模式,对于十万甚至百万连接的时候,传统BIO模型是无能为力的:
①线程的创建和销毁成本很高,在linux中,线程本质就是一个进程,创建销毁都是重量级的系统函数
②线程本身占用较大的内存,像java的线程栈一般至少分配512K-1M的空间,如果系统线程过高,内存占用是个问题
③线程的切换成本高,操作系统发生线程切换的时候,需要保留线程的上下文,然后执行系统调用,如果线程数过高可能执行线程切换的时间甚至大于线程执行的时间,这时候带来的表现是系统load偏高,CPUsy使用率很高
④容易造成锯齿状的系统负载。系统负载是用活动线程数或CPU核心数,一旦线程数量高但外部网络环境不是很稳定,就很容易造成大量请求的结果同时返回,激活大量阻塞线程从而使系统负载压力过大。
4.NIO同步非阻塞
NIO基于Reactor,当socket有流可读或可写入socket,操作系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操作系统。也就是,不是一个链接就要对应一个处理线程,而是一个有效请求对应一个线程,当连接没有数据时,是没有工作线程来处理的