文章目录
-
-
-
1、请描述JVM、JRE和JDK的关系?
-
2、如果main方法被声明为private会怎样?
-
3、&和&&的区别在哪里?
-
4、char类型的变量可不可以存汉字?
-
5、a+=b 和a=a+b的区别?
-
6、不使用第三变量交换两个变量的值
-
7、String s = new String(“xyz”)创建了几个String Object?
-
8、hashcode和equals的关系
-
9、最大公约数算法
-
10、final, finally, finalize 的区别?
-
11、Java中的Math.round(-1.5)等于多少?
-
1、常见的几种运行时异常?
-
2、 String、StringBuffer、StringBuilder 的区别?
-
3、基本数据类型有哪些,string是基本数据类型吗
-
5、过滤器和拦截器区别
-
6、String s = “hello”和String s = new String(“hello”);区别
-
7、一个java程序是怎样运行起来的?
-
8、什么时候会用到单例模式?
-
9、JDK1.5之前,switch循环只支持char、byte、short、int四种数据类型。
-
-
1、请描述JVM、JRE和JDK的关系?
JDK
(java开发工具包)
Java Development Kit
是提供给Java开发人员使用的,其中包含了Java的开发工具和JRE。所以安装了JDK,就无需再单独安装JRE了。其中的
开发工具
:
编译工具(javac.exe)
,
打包工具(jar.exe)
等
JRE
(java运行时环境)
Java Runtime Environment包括
Java虚拟机
和Java程序所需的
核心类库
等。
核心类库
主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等,系统缺省加载这个包。
如果想要运行一个开发好的Java程序,计算机中只需要安装JRE即可。
JVM
(java虚拟机)
Java Virtual Machine
是Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。
2、如果main方法被声明为private会怎样?
main()使程序的主入口,也是程序必须运行的通道,所以声明private会报错。
public class Test {
private static void main(String[] args) {
System.out.println("Hello");
}
}
结果:
编译没问题,执行报错。
错误: 找不到或无法加载主类 Test
原因: java.lang.NoClassDefFoundError: Algorithm/Test (wrong name: Test)
3、&和&&的区别在哪里?
&
:按位与(二进制按位与)
&&
:逻辑与,返回值为boolean.
public static void main(String[] args) {
/*
按位与,按二进制位进行与运算
00000100 4
00000101 5
00000100结果为4
*/
System.out.println(4 & 5);
//&&短路运算:前面是false后边就不会计算
System.out.println(false && (10 > 20));
}
4、char类型的变量可不可以存汉字?
答案:
是可以的,char类型中存储的是
Unicode编码
,Unicode编码中是存在中文的,所以Char自然可以存储汉字。
但是!仅限于Unicode中存在的汉字。一个汉字的占两个字节,一个Unicode也是占两个字节 ,char存储汉字完全没有问题。
5、a+=b 和a=a+b的区别?
- 数字类型的常量在java里面默认都是int类型
- short,byte类型的数相加,都会提升为int类型
public static void main(String[] args) {
//数字类型的常量在java里面默认都是int类型
//short,byte类型的数相加,都会提升为int类型
short a = 10;
short b = 8;
//a = a+b;//编译报错:因为a+b结果是int,却赋值给了short a
a = (short)(a+b);
System.out.println(a);
/*
+= : 是java中的一个运算符,而不是两个,
所以在运算时会进行自动类型转换。所以在编译时没有报错。
*/
a+=b;//正确!!
}
+=
: 是java中的一个运算符,而不是两个,所以在运算时会进行自动类型转换。所以在编译时没有报错。
6、不使用第三变量交换两个变量的值
public class Test01 {
//方式一
public static void main(String[] args) {
int a = 10;
int b = 20;
a = a+b;
b = a-b;
a = a-b;
System.out.println(a);//20
System.out.println(b);//10
}
//方式二
public static void main(String[] args) {
int a = 10;
int b = 20;
a = a*b;
b = a/b;
a = a/b;
System.out.println(a);//20
System.out.println(b);//10
}
//方式三
public static void main(String[] args) {
int a = 10;
int b = 20;
//a = b+(b=a)*0;
a = b-(b=a)*0;//从左往右
System.out.println(a);//20
System.out.println(b);//10
}
}
7、String s = new String(“xyz”)创建了几个String Object?
一个或者两个。
8、hashcode和equals的关系
public class Test02HashCodeEquals {
/**
* Hash是散列的意思
* 就是把任意长度的输入,通过散列算法变换成固定长度的输出,该输出就是散列值。
* 1、不同关键字经过散列算法变换后可能得到同一个散列地址,这种现象称为碰撞,hash碰撞。
* 2、如果两个hash值不同(前提是同一hash算法),那么这两个hash值对应原始数据必定不同。
* @param args
*/
public static void main(String[] args) {
String s1 = "重地";
String s2 = "通话";
System.out.println(s1.hashCode());//1179395
System.out.println(s2.hashCode());//1179395
//hashcode的作用是为了获取哈希吗,也称为散列码,返回int类型的整数。
/*
1、hashcode的存在主要是为了提高在散列结构中查找的效率,在线性表中没有作用。
2、两个相等对象,分别调用equals方法时都会返回true
3、如果两个对象equals相等,则hashcode一定也是相同的。
4、两个对象的hashcode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置。
5、因此,equals方法被覆盖过,则hashcode方法也必须被覆盖。
6、hashcode()的默认行为是对堆上的对象产生独特的值。
*/
}
}
9、最大公约数算法
public class Test03 {
public static void main(String[] args) {
main1();
main2();
}
public static void main1() {
int a = 2;
int b = 3;
int min = a>b?b:a;
int result=0;
for (int i = min; i >1; i--) {
if(a%i==0 && b%i==0){
result=i;
break;
}
}
System.out.println("最大公约数是:"+result);
}
public static void main2() {
int a = 5;
int b = 7;
int max = a>b?a:b;
for (int i = max; i <=a*b ; i++) {
if(i%a==0 && i%b==0){
System.out.println("最小公倍数是:"+i);
break;
}
}
}
}
10、final, finally, finalize 的区别?
final
用于声明属性,方法和类, 分别表示属性不可变, 方法不可覆盖, 类不可继承.
finally
是异常处理语句结构的一部分,表示总是执行.
finalize
是
Object
类的一个方法,
在垃圾收集器执行的时候会调用被回收对象的此方法
,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等. JVM不保证此方法总被调用.
11、Java中的Math.round(-1.5)等于多少?
public static void main(String[] args) {
//返回int,四舍五入
System.out.println(Math.round(1.5));//2
System.out.println(Math.round(1.2));//1
System.out.println(Math.round(-1.5));//-1
//向下取整,整浮点数
System.out.println(Math.floor(-1.5));//-2.0
System.out.println(Math.floor(1.5));//1.0
System.out.println(Math.floor(1.6));//1.0
//向上取整,整浮点数
System.out.println(Math.ceil(-1.5));//-1.0
System.out.println(Math.ceil(1.5));//2.0
System.out.println(Math.ceil(-1.6));//-1.0
}
1、常见的几种运行时异常?
Q3:写出你最常见的5个RuntimeException?
-
java.lang.
NullPointerException
(空指针异常):调用了未经初始化的对象或者是不存在的对象。 -
java.lang.
ClassNotFoundException
(指定的类找不到):类的名称和路径加载错误;通常都是程序试图通过字符串来加载某个类时可能引发的异常。 -
java.lang.
NumberFormatException
(数字格式异常):字符型数据中包含非数字型字符。 -
java.lang.
IndexOutOfBoundsException
(数组下标越界异常):常见于操作数组对象时发生。 -
java.lang.
IllegalArgumentException
:方法传递参数错误。 -
java.lang.
ClassCastException
:数据类型转换异常。 -
java.lang.
InterruptedException
: (中断异常)当线程在活动之前或活动期间处于正在等待、休眠或占用状态且该线程被中断时,抛出该异常。有时候,一种方法可能希望测试当前线程是否已被中断,如果已被中断,则立即抛出此异常。下列代码可以达到这种效果:
IllegalArgumentException不合法的参数异常
一个简单的小例子:
package Test2;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test3 {
public static void main(String[] args) {
Date day = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = df.format(day);
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM");
String format = dateFormat.format(date);
System.out.println(format);
}
}
运行会报错:
无法将给定的对象作为日期格式化,即因为传递了一个错误的参数。
Exception in thread "main" java.lang.IllegalArgumentException: Cannot format given Object as a Date
at java.text.DateFormat.format(DateFormat.java:281)
at java.text.Format.format(Format.java:140)
at Test2.Test3.main(Test3.java:14)
2、 String、StringBuffer、StringBuilder 的区别?
可变性:
String类中使用字符数组保存字符串,
private final char value[]
,所以string对象是不可变的。
StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,
char[] value
,这两种对象都是可变的。
线程安全性:
StringBuffer是线程安全的,StringBuilder是线程不安全的,StringBuffer在StringBuilder的方法之上加了同步锁(
synchronized
)修饰,保证线程安全。但他们两个中的所有方法都是相同的。
性能
每次对String 类型进行修改的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。
StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。
相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。
StringBuilder , StringBuffer ,String 都是 final 的
对于三者使用的总结
如果要操作少量的数据用 = String
单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
补充:
如果一个String类型的字符串,在编译时就可以确定是一个字符串常量,则编译完成之后,字符串会自动拼接成一个常量。此时String的速度比StringBuilder和StringBuffer的性能更好。
StringBuilder , StringBuffer ,String 都是
final
的,但是为什么StringBuilder , StringBuffer可以进行修改呢?
因为不可变包括的是,引用不可变以及对象不可变,而这三个都是属于引用不可变(也就是地址不要变,里面的内容随心所欲),而StringBuilder , StringBuffer 中都包含右append方法,可对对象中的内容进行增加。而String a=“123”+new String(“456”);实际上底层是用了一个StringBuffer 进行append;
3、基本数据类型有哪些,string是基本数据类型吗
Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;
除了基本类型(primitive type),剩下的都是引用类型(referencetype),
Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。
String的引入
Java 的 8 种基本数据类型中不包括 String,基本数据类型中用来描述文本数据的是 char,但是它只能表示单个字符,比如 ‘a’,‘好’ 之类的,如果要描述一段文本,就需要用多个 char 类型的变量,也就是一个 char 类型数组,比如“你好” 就是长度为2的数组 char[] chars = {‘你’,‘好’};
但是使用数组过于麻烦,所以就有了 String,String 底层就是一个 char 类型的数组,只是使用的时候开发者不需要直接操作底层数组,用更加简便的方式即可完成对字符串的使用。
5、过滤器和拦截器区别
过滤器
:是 servlet 规范中的一部分,任何 java web 工程都可以使用。在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截。
拦截器
:是SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用。它是只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的。
6、String s = “hello”和String s = new String(“hello”);区别
String s = new String("hello");
可能创建两个对象也可能创建一个对象。如果常量池中有hello字符串常量的话,则仅仅在堆中创建一个对象。如果常量池中没有hello对象,则堆上和常量池都需要创建。
String s = "hello"
这样创建的对象,JVM会直接检查字符串常量池是否已有”hello”字符串对象,如没有,就分配一个内存存放”hello”,如有了,则直接将字符串常量池中的地址返回给栈。(没有new,没有堆的操作)
7、一个java程序是怎样运行起来的?
- 程序员写.java
- 编译成.class
- 启动主线程
- 类加载器启动
- 加载main方法存在的类
- 之后就是遇到一个类 加载一个class文件
- 方法存在在方法栈中,参数存在堆会和栈中
8、什么时候会用到单例模式?
-
在应用场景中,
某类只要求生成一个对象的时候
,如一个班中的班长、每个人的身份证号等。 -
当对象需要被共享的场合
。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。 -
当某类需要频繁实例化,而创建的对象又频繁被销毁的时候
,如多线程的线程池、网络连接池等。
9、JDK1.5之前,switch循环只支持char、byte、short、int四种数据类型。
JDK1.5开始,switch循环中增加了枚举类与byte short char int的包装类,对四个包装类的支持是因为java编译器在底层手动进行拆箱,而对枚举类的支持是因为枚举类有一个ordinal方法,该方法实际上是一个int类型的数值。
JDK1.5之后支持的类型:char、byte、short、int 、Character、Byte、Short、Integer 、枚举。
JDK1.7开始,switch循环支持String类型,但实际上String类型有一个hashCode算法,结果也是int类型.而byte short char类型可以在不损失精度的情况下向上转型成int类型.所以总的来说,可以认为switch中只支持int。JDK1.7之后支持的类型:char、byte、short、int 、Character、Byte、Short、Integer 、String、枚举。
注:switch中,表达式不能为空,为空会抛出NullPointerException。case项即不能为空也不能重复,这两种情况都会出现编译错误。