一、Java 基础
1.JDK 和 JRE 有什么区别?
答:JRE: Java Runtime Environment
JDK:Java Development Kit
JRE顾名思义是java运行时环境,包含了java虚拟机,java基础类库。是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的。
JDK顾名思义是java开发工具包,是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具:jconsole,jvisualvm等工具软件,还包含了java程序编写所需的文档和demo例子程序。
如果安装了JDK,会发同你的电脑有两套JRE,一套位于 \jre 另外一套位于 C:\Program Files\Java\j2re1.4.1_01 目录下,后面这套比前面那套少了Server端的Java虚拟机
2.== 和 equals 的区别是什么?
答:==:比较引用类型比较的是地址值是否相同
equals:比较引用类型默认也是比较地址值是否相同,注意:String类重写了equals()方法,比较的是内容是否相同。
3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?
答:首先了解hashCode()的用途,HashCode的存在主要是为了查找的快捷性,HashCode是用来在散列存储结构中确定对象的存储地址的。
由上一题我们可以得知,equals是默认比较地址值是否相同,String类的equals方法则比较内容是否相同。
所以可以得出结论:
( 1.如果两个对象相同,那么它们的hashCode值一定要相同;
2.如果两个对象的hashCode相同,它们并不一定相同(这里说的对象相同指的是用eqauls方法比较)。
如不按要求去做了,会发现相同的对象可以出现在Set集合中,同时,增加新元素的效率会大大下降。
3.equals()相等的两个对象,hashcode()一定相等;equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。
换句话说,equals()方法不相等的两个对象,hashcode()有可能相等(我的理解是由于哈希码在生成的时候产生冲突造成的)。反过来,hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。
---------------------
作者:flyingsen
来源:CSDN
原文:https://blog.csdn.net/zj15527620802/article/details/88547914
版权声明:本文为博主原创文章,转载请附上博文链接!)
4.final 在 java 中有什么作用?
答:final关键字可以用于三个地方。用于修饰类、类属性和类方法。
被final关键字修饰的类不能被继承,被final关键字修饰的类属性和类方法不能被覆盖(重写);
5.java 中的 Math.round(-1.5) 等于多少?
答:math.round是四舍五入函数,这题扩展一下应该和Math.round(1.5)等于多少进行比较。
Math.round(-1.5) = -2 Math.round(1.5)= 2
四舍五入的原理是在参数上加0.5然后做向下取整。
6.String 属于基础的数据类型吗?
答:String不属于基础的数据类型,是final修饰的java类。
拓展一下下。Java的八大基础数据类型:
1 字符类型:byte,char
2 基本整型:short,int,long
3 浮点型:float,double
4 布尔类型:boolean
7.java 中操作字符串都有哪些类?它们之间有什么区别?
答:(String、StringBuffer、StringBuilder
String : final修饰,String类的方法都是返回new String。即对String对象的任何改变都不影响到原对象,对字符串的修改操作都会生成新的对象。
StringBuffer : 对字符串的操作的方法都加了synchronized,保证线程安全。
StringBuilder : 不保证线程安全,在方法体内需要进行字符串的修改操作,可以new StringBuilder对象,调用StringBuilder对象的append、replace、delete等方法修改字符串。
---------------------
作者:ConstXiong
来源:CSDN
原文:https://blog.csdn.net/meism5/article/details/89328490
版权声明:本文为博主原创文章,转载请附上博文链接!)
区别:String是不可变的对象,对每次对String类型的改变时都会生成一个新的对象,StringBuffer和StringBuilder是可以改变对象的。
对于操作效率:StringBuilder > StringBuffer > String
对于线程安全:StringBuffer 是线程安全,可用于多线程;StringBuilder 是非线程安全,用于单线程
不频繁的字符串操作使用 String。反之,StringBuffer 和 StringBuilder 都优于String
8.String str="i"与 String str=new String("i")一样吗?
答:不一样
前者内存会去查找永久代(常量池) ,如果没有的话,在永久代中中开辟一块儿内存空间,把地址付给栈指针,如果已经有了"ABC"的内存,直接把地址赋给栈指针;所以如果String str=“i” String str1=“i” String str2=“i”时,str==str1==str2
后者是根据"i"这个String对象再次构造一个String对象;在堆中从新new一块儿内存,把指针赋给栈,将新构造出来的String对象的引用赋给str。 因此 只要是new String(),则,栈中的地址都是指向最新的new出来的堆中的地址。
9.如何将字符串反转?
答:方法1 递归方法:
public static String reverse1(String s) {
int length = s.length();
if (length <= 1){
return s;
}
String left = s.substring(0, length / 2);
String right = s.substring(length / 2, length);
return reverse1(right) + reverse1(left);
}
方法2 通过 charAt(int index)返回char值进行字符串拼接
public static String reverse2(String s) {
int length = s.length();
String reverse = "";
for (int i = 0; i < length; i++)
reverse = s.charAt(i) + reverse;
return reverse;
}
方法3 把字符串转换成字符数组倒叙拼接然后返回值
public static String reverse3(String s) {
char[] array = s.toCharArray();
String reverse = "";
for (int i = array.length - 1; i >= 0; i--)
reverse += array[i];
return reverse;
}
方法4 调用StringBuffer中的reverse方法
publicstatic String reverse4(String s) {
returnnew StringBuffer(s).reverse().toString();
}
方法5 把字符串转换成字符数组首位对调位置
public static String reverse5(String orig) {
char[] s = orig.toCharArray();
int n = s.length - 1;
int halfLength = n / 2;
for (int i = 0; i <= halfLength; i++) {
char temp = s[i];
s[i] = s[n - i];
s[n - i] = temp;
}
return new String(s);
}
方法6
public static String reverse6(String s) {
char[] str = s.toCharArray();
int begin = 0;
int end = s.length() - 1;
while (begin < end) {
str[begin] = (char) (str[begin] ^ str[end]);
str[end] = (char) (str[begin] ^ str[end]);
str[begin] = (char) (str[end] ^ str[begin]);
begin++;
end--;
}
return new String(str);
}
方法7
import java.util.Stack;
public class StringReverse {
public static String reverse7(String s) {
char[] str = s.toCharArray();
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < str.length; i++)
stack.push(str[i]);
String reversed = "";
for (int i = 0; i < str.length; i++)
reversed += stack.pop();
return reversed;
}
}
作者:绝不妥协绝不低头
来源:博客园
原文:https://www.cnblogs.com/lanseyitai1224/p/6955609.html
10.String 类的常用方法都有那些?
答:下面列举了20个常用方法。格式:返回类型 方法名 作用。
1、和长度有关:
int length() 得到一个字符串的字符个数
2、和数组有关:
byte[] getByte() ) 将一个字符串转换成字节数组
char[] toCharArray() 将一个字符串转换成字符数组
String split(String) 将一个字符串按照指定内容劈开
3、和判断有关:
boolean equals() 判断两个字符串的内容是否一样
boolean equalsIsIgnoreCase(String) 忽略太小写的比较两个字符串的内容是否一样
boolean contains(String) 判断一个字符串里面是否包含指定的内容
boolean startsWith(String) 判断一个字符串是否以指定的内容开头
boolean endsWith(String) 判断一个字符串是否以指定的内容结尾
4、和改变内容有关:
String toUpperCase() 将一个字符串全部转换成大写
String toLowerCase() 将一个字符串全部转换成小写
String replace(String,String) 将某个内容全部替换成指定内容
String replaceAll(String,String) 将某个内容全部替换成指定内容,支持正则
String repalceFirst(String,String) 将第一次出现的某个内容替换成指定的内容
String substring(int) 从指定下标开始一直截取到字符串的最后
String substring(int,int) 从下标x截取到下标y-1对应的元素
String trim() 去除一个字符串的前后空格
5、和位置有关:
char charAt(int) 得到指定下标位置对应的字符
int indexOf(String) 得到指定内容第一次出现的下标
int lastIndexOf(String) 得到指定内容最后一次出现的下标
11.抽象类必须要有抽象方法吗?
答:抽象类中不一定要包含抽象(abstrace)方法。也就是了,抽象中可以没有抽象(abstract)方法。反之,类中含有抽象方法,那么类必须声明为抽象类。
12.普通类和抽象类有哪些区别?
答:1.抽象类不能被实例化。
2.抽象类可以有构造函数,被继承时子类必须继承父类一个构造方法,抽象方法不能被声明为静态。
3.抽象方法只需申明,而无需实现,抽象类中可以允许普通方法有主体
4.含有抽象方法的类必须申明为抽象类
5.抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类。
拓展一下:抽象类是否可以有构造函数?答案是可以有。抽象类的构造函数用来初始化抽象类的一些字段,而这一切都在抽象类的派生类实例化之前发生。不仅如此,抽线类的构造函数还有一种巧妙应用:就是在其内部实现子类必须执行的代码
13.抽象类能使用 final 修饰吗?
答:不能,抽象类是被用于继承的,final修饰代表不可修改、不可继承的。(抽象类中的抽象方法是未来继承之后重写方法,而用final修饰的类,无法被继承。)
14.接口和抽象类有什么区别?
答:a. 抽象类可以有构造方法,接口中不能有构造方法。
b. 抽象类中可以有普通成员变量,接口中没有普通成员变量。
c. 抽象类中可以包含非抽象普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的方法。
d. 抽象类中的抽象方法的访问权限可以是 public、protected 和(默认类型,虽然 eclipse 不报错,但也不能用,默认类型子类不能继承),接口中的抽象方法只能是 public 类型的,并且默认即为 public abstract 类型。
e. 抽象类中可以包含静态方法,在 JDK1.8 之前接口中不能不包含静态方法,JDK1.8 以后可以包含。
f. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问权限可以是任意的,但接口中定义的变量只能是 public static final 类型的,并且默认即为 public static final 类型。
g. 一个类可以实现多个接口,用逗号隔开,但只能继承一个抽象类,接口不可以实现接口,但可以继承接口,并且可以继承多个接口,用逗号隔开。
h.接口是设计的结果 ,抽象类是重构的结果
15.java 中 IO 流分为几种?
答:•按照流的流向分,可以分为输入流和输出流;
•按照操作单元划分,可以划分为字节流和字符流;
•按照流的角色划分为节点流和处理流。
Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0流的40多个类都是从如下4个抽象类基类中派生出来的。
1.字节输入流(InputStream)
2.字节输出流(OutputStream)
3.字符输入流(Reader)
4.字符输出流(Writer)
---------------------
作者:qfc8930858
来源:CSDN
原文:https://blog.csdn.net/qfc8930858/article/details/89493877
版权声明:本文为博主原创文章,转载请附上博文链接!
16.BIO、NIO、AIO 有什么区别?
答:•BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。
•NIO (New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。NIO中的N可以理解为Non-blocking,不单纯是New。它支持面向缓冲的,基于通道的I/O操作方法。NIO提供了与传统BIO模型中的 Socket 和 ServerSocket 相对应的 SocketChannel 和 ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发
•AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。
---------------------
作者:qfc8930858
来源:CSDN
原文:https://blog.csdn.net/qfc8930858/article/details/89493877
版权声明:本文为博主原创文章,转载请附上博文链接!
17.Files的常用方法都有哪些?
答:
创建:
createNewFile()在指定位置创建一个空文件,成功就返回true,如果已存在就不创建,然后返回false。
mkdir() 在指定位置创建一个单级文件夹。
mkdirs() 在指定位置创建一个多级文件夹。
renameTo(File dest)如果目标文件与源文件是在同一个路径下,那么renameTo的作用是重命名, 如果目标文件与源文件不是在同一个路径下,那么renameTo的作用就是剪切,而且还不能操作文件夹。
删除:
delete() 删除文件或者一个空文件夹,不能删除非空文件夹,马上删除文件,返回一个布尔值。
deleteOnExit()jvm退出时删除文件或者文件夹,用于删除临时文件,无返回值。
判断:
exists() 文件或文件夹是否存在。
isFile() 是否是一个文件,如果不存在,则始终为false。
isDirectory() 是否是一个目录,如果不存在,则始终为false。
isHidden() 是否是一个隐藏的文件或是否是隐藏的目录。
isAbsolute() 测试此抽象路径名是否为绝对路径名。
获取:
getName() 获取文件或文件夹的名称,不包含上级路径。
getAbsolutePath()获取文件的绝对路径,与文件是否存在没关系
length() 获取文件的大小(字节数),如果文件不存在则返回0L,如果是文件夹也返回0L。
getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回null。
lastModified()获取最后一次被修改的时间。
文件夹相关:
static File[] listRoots()列出所有的根目录(Window中就是所有系统的盘符)
list() 返回目录下的文件或者目录名,包含隐藏文件。对于文件这样操作会返回null。
listFiles() 返回目录下的文件或者目录对象(File类实例),包含隐藏文件。对于文件这样操作会返回null。
list(FilenameFilter filter)返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。
listFiles(FilenameFilter filter)返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。
测试代码:
package com.file;
import java.io.File;
import java.io.IOException;
/**
* file相关的方法
*
* @author coco_xu
*
*/
public class FileMethodTest {
public static void main(String[] args) throws IOException {
File fileCreate = new File("D:\\coco_xu\\study\\files\\file.txt");
// 创建单级文件夹
System.out.println("单级文件夹创建:" + fileCreate.mkdir());
// 创建多级文件夹
System.out.println("多级文件夹创建:" + fileCreate.mkdirs());
//创建文件
System.out.println("创建文件:" + fileCreate.createNewFile());
//文件重命名
File toFile = new File("D:\\coco_xu\\study\\files\\toFile.txt");
System.out.println("文件重命名:" + fileCreate.renameTo(toFile));
// 删除方法
File file = new File("D:\\coco_xu\\study\\files\\toFile.tx");
System.out.println("删除文件:" + file.delete());
file.deleteOnExit();
// 判断方法
/*
* File file = new File("F:\\a.txt");
* System.out.println("文件或者文件夹存在吗?"+file.exists());
* System.out.println("是一个文件吗?"+file.isFile());
* System.out.println("是一个文件夹吗?"+file.isDirectory());
* System.out.println("是隐藏文件吗?"+file.isHidden());
* System.out.println("此路径是绝对路径名?"+file.isAbsolute());
*/
// 获取方法
/*
* File file = new File("f:\\a.txt");
* System.out.println("文件或者文件夹得名称是:"+file.getName());
* System.out.println("绝对路径是:"+file.getPath());
* System.out.println("绝对路径是:"+file.getAbsolutePath());
* System.out.println("文件大小是(以字节为单位):"+file.length());
* System.out.println("父路径是"+file.getParent()); //使用日期类与日期格式化类进行获取规定的时间 long
* lastmodified= file.lastModified(); Date data = new Date(lastmodified);
* SimpleDateFormat simpledataformat = new
* SimpleDateFormat("YY年MM月DD日 HH:mm:ss");
* System.out.println("最后一次修改的时间是:"+simpledataformat.format(data));
*/
// 文件或者文件夹的方法
/*
* File[] file = File.listRoots(); System.out.println("所有的盘符是:"); for (File item
* : file) { System.out.println("\t" + item); } File filename = new
* File("D:\\coco_xu"); String[] name = filename.list();
* System.out.println("指定文件夹下的文件或者文件夹有:"); for (String item : name) {
* System.out.println("\t" + item); } File[] f = filename.listFiles();
* System.out.println("获得该路径下的文件或文件夹是:"); for (File item : f) {
* System.out.println("\t" + item.getName()); }
*/
}
}
转载自:https://www.cnblogs.com/cocoxu1992/p/10460994.html