Java面试基础

1.JDK 和 JRE 有什么区别?

JREJava Runtime Environment的缩写,顾名思义是java运行时环境,包含了java虚拟机,java基础类库。是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的,还有所有的Java类库的class文件,都在lib目录下,并且都打包成了jar

Jdk是Java Development Kit的缩写,顾名思义是java开发工具包,是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具:jconsole,jvisualvm等工具软件,还包含了java程序编写所需的文档和demo例子程序。

如果你需要运行java程序,只需安装JRE就可以了。如果你需要编写java程序,需要安装JDK。

 

2.== 和 equals 的区别是什么?

 ==

== 比较的是变量()内存中存放的对象的()内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。

1、比较的是操作符两端的操作数是否是同一个对象
2、两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
3、比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为true,如:
int a=10 long b=10L double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。

equals

  equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。

  String s="abce"是一种非常特殊的形式,new 有本质的区别。它是java唯一不需要new 就可以产生对象的途径。以String s="abce";形式赋值在java中叫直接量,它是在常量池中而不是象new一样放在压缩堆中。这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abcd"的对象,如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中新创建一个"abcd",下一次如果有String s1 = "abcd";又会将s1指向"abcd"这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象.
  而String s = new String("abcd");和其它任何对象一样.每调用一次就产生一个对象,只要它们调用。

  也可以这么理解: String str = "hello"; 先在内存中找是不是有"hello"这个对象,如果有,就让str指向那个"hello".如果内存里没有"hello",就创建一个新的对象保存"hello". String str=new String ("hello") 就是不管内存里是不是已经有"hello"这个对象,都新建一个对象保存"hello"

3.两个对象的 hashCode()相同,则 equals()也一定为 true,对吗? No

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数。

在散列表中,

    1、如果两个对象相等,那么它们的hashCode()值一定要相同;

    2、如果两个对象hashCode()相等,它们并不一定相等。

注意:这是在散列表中的情况。在非散列表中一定如此!

总而言之,就是一切取决于hashCode和equals怎么重写的,如果hashCode和equals都没有重写,就按上面的来

4.final 在 java 中有什么作用?

1、final成员变量表示常量,如果final指针,那么指针地址不可以改变,但是指针指向的对象可以改变

2、final类不能继承

3、final方法不能重写,但是可以继承

3、final不能修饰构造函数

注意:父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。

byte b1=1;

byte b2=3;

byte b3=b1+b2;

以上最后一行直接报错,因为byte相加会直接转换成int,int赋值给byte会发生截断,会报错。

final byte b1=1;

final byte b2=3;

byte b3=b1+b2;

以上可以通过编译,因为一切都是确定的,所以编译期间就确定了变量值且不改变。

final byte b1=6;

final byte b2=125;

byte b3=b1+b2;

以上最后一行直接报错,因为byte相加会溢出,编译截断报错。

5.java 中的 Math.round(-1.5) 等于多少? -1

Math.round()的原理是对传入的参数+0.5之后,再向下取整得到的数就是返回的结果,返回值为long型。这里的向下取整是说取比它小的第一个整数或者和它相等的整数。-1.5+0.5=-1向下取整为-1,。

向下取整:Math.floor();Math.floor(1.3)=1

向上取整:Math.ceil(); Math.ceil(1.2)=2

6.String 属于基础的数据类型吗?

很明显不是,很简单判断方法,大写开头是类,小写开头是基本数据类型。

String是final修饰的java类,java中的基本类型一共有8个,它们分别为:

1、字符类型:byte,char

2、基本整型:short,int,long

3、浮点型:float,double

4、布尔类型:boolean

7.java 中操作字符串都有哪些类?它们之间有什么区别?

String、StringBuffer和StringBuilder

  1. 首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:

效率:StringBuilder > StringBuffer > String

  String最慢的原因:

  String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。以下面一段代码为例:

    String str="abc";

    System.out.println(str);

    str=str+"de";

    System.out.println(str);

如果运行这段代码会发现先输出“abc”,然后又输出“abcde”,好像是str这个对象被更改了,其实,这只是一种假象罢了,JVM对于这几行代码是这样处理的,首先创建一个String对象str,并把“abc”赋值给str,然后在第三行中,其实JVM又创建了一个新的对象也名为str,然后再把原来的str的值和“de”加起来再赋值给新的str,而原来的str就会被JVM的垃圾回收机制(GC)给回收掉了,所以,str实际上并没有被更改,也就是前面说的String对象一旦创建之后就不可更改了。所以,Java中对String对象进行的操作实际上是一个不断创建新的对象并且将旧的对象回收的一个过程,所以执行速度很慢。

而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。另外,有时候我们会这样对字符串进行赋值:

    String str="abc"+"de";

    StringBuilder stringBuilder=new StringBuilder().append("abc").append("de");

    System.out.println(str);

    System.out.println(stringBuilder.toString());

这样输出结果也是“abcde”和“abcde”,但是String的速度却比StringBuilder的反应速度要快很多,这是因为第1行中的操作和

  String str="abcde";

  是完全一样的,所以会很快,而如果写成下面这种形式

    String str1="abc";

    String str2="de";

    String str=str1+str2;

那么JVM就会像上面说的那样,不断的创建、回收对象来进行这个操作了。速度就会很慢。

 

2. 再来说线程安全

在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的

如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。

 

3. 总结一下

String:适用于少量的字符串操作的情况

StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况

StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

8.String str="i"与 String str=new String("i")一样吗?

1.当使用String str="abc",这种方式时,先去内存的Heap中找是否存在"abc"这个字符串,若存在,则将地址引用。若不存在则创建。

2.当使用String str=new String("abc");时,不管事先是否存在"abc",每次都会创建其新的对象。

测试一下:

String s1="abc";

String s2="abc";

String s3=new String("abc");

String s4=new String("abc");

System.out.println(s1 == s2);

System.out.println(s2 == s3);

System.out.println(s1 == s3);

System.out.println(s4 == s3);

打印的结果为:

true

false

false

false

9.如何将字符串反转?

两种好理解简单的方法:

1、直接用StringBuffer自带的方法

public static String reverse1(String s) {

    return new StringBuffer(s).reverse().toString();

 }

2、 把字符串转换成字符数组首位对调位置

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);

 }

10.String 类的常用方法都有那些?

char charAt(int index);//返回指定索引处的 char 值。

int compareTo(String anotherString) ;//按字典顺序比较两个字符串。

String concat(String str) ;将指定字符串连接到此字符串的结尾。

boolean contains(CharSequence s);当且仅当此字符串包含指定的 char 值序列时,返回 true。

boolean endsWith(String suffix) ;//测试此字符串是否以指定的后缀结束。

boolean equals(Object anObject) ;//将此字符串与指定的对象比较。

byte[] getBytes();//使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。

int  indexOf(int ch);//返回指定字符在此字符串中第一次出现处的索引。

int  lastIndexOf(int ch) ;//返回指定字符在此字符串中最后一次出现处的索引。

int  length();//返回此字符串的长度。

String[] split(String regex);//根据给定正则表达式的匹配拆分此字符串。

boolean  startsWith(String prefix);//测试此字符串是否以指定的前缀开始。

char[]  toCharArray();//将此字符串转换为一个新的字符数组。

String  toUpperCase();//使用默认语言环境的规则将此 String 中的所有字符都转换为大写。

String trim();//返回字符串的副本,忽略前导空白和尾部空白。

String  toLowerCase(Locale locale);//使用给定 Locale 的规则将此 String 中的所有字符都转换为小写。

11.抽象类必须要有抽象方法吗?

抽象类可以不包含抽象方法,包含抽象方法的类一定是抽象类。

 

12.普通类和抽象类有哪些区别?

1、抽象类不能被实例化。

2、抽象类可以有构造函数,被继承时子类必须继承父类一个构造方法,抽象方法不能被声明为静态。

3、抽象方法只需申明,而无需实现,抽象类中可以允许普通方法有主体

4、含有抽象方法的类必须申明为抽象类

5、抽象的子类必须实现抽象类中所有抽象方法,否则这个子类也是抽象类。

13.抽象类能使用 final 修饰吗?

java类一旦被声明为abstract(抽象类),必须要继承或者匿名(其实匿名也是种继承)才能使用。

而final则是让该类无法被继承,所以final是必然不能和abstract同时声明的

但是private呢?一个类被声明为private的时候,它当然是内部类,内部类是可以被它的外部类访问到的,所以,可以继承,private和abstract不冲突。

13.抽象类能使用 final 修饰吗?

java类一旦被声明为abstract(抽象类),必须要继承或者匿名(其实匿名也是种继承)才能使用。

而final则是让该类无法被继承,所以final是必然不能和abstract同时声明的

但是private呢?一个类被声明为private的时候,它当然是内部类,内部类是可以被它的外部类访问到的,所以,可以继承,private和abstract不冲突。

14.接口和抽象类有什么区别?

抽象类是用来捕捉子类的通用特性的 。它不能被实例化,只能被用作子类的超类。抽象类是被用来创建继承层级里子类的模板。

接口是抽象方法的集合。如果一个类实现了某个接口,那么它就继承了这个接口的抽象方法。这就像契约模式,如果实现了这个接口,那么就必须确保使用这些方法。接口只是一种形式,接口自身不能做任何事情。

15.java 中 IO 流分为几种?

Java中的流,可以从不同的角度进行分类。

按照数据流的方向不同可以分为:输入流和输出流。

按照处理数据单位不同可以分为:字节流和字符流。

按照实现功能不同可以分为:节点流和处理流。

 

16.BIO、NIO、AIO 有什么区别?

  IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。  https://blog.csdn.net/skiof007/article/details/52873421

17.File的常用方法都有哪些?

//1.1创建对象

File file=new File("d:\\123.txt");

//1.2判断文件是否存在

 

if(!file.exists()){

file.createNewFile();

}

//1.3删除

file.delete();

file.deleteOnExit();//退出jvm,删除文件

//1.4可执行、可读、可写

file.canExecute();

file.canRead();

file.canWrite();

//1.5获取

file.getAbsoulatePath();

file.getPath();

file.getName();

file.getParent();

file.lastModified();//修改时间

//1.6判断

file.isFile();

file.isHidden();

file.renameTo();//重命名

文件夹 :

//2.1创建文件夹

File dir=new File("d:\\aaa\\bbb");

//2.2判断是否存在

等等

你可能感兴趣的:(java)