1. static关键字的作用
Static可以修饰内部类、方法、变量、代码块
Static修饰的类是静态内部类
Static修饰的方法是静态方法,表示该方法属于当前类的,而不属于某个对象的,静态方法也不能被重写,可以直接使用类名来调用。在static方法中不能使用this或者super关键字。
Static修饰变量是静态变量或者叫类变量,静态变量被所有实例所共享,不会依赖于对象。静态变量在内存中只有一份拷贝,在JVM加载类的时候,只为静态分配一次内存。
Static修饰的代码块叫静态代码块,通常用来做程序优化的。静态代码块中的代码在整个类加载的时候只会执行一次。静态代码块可以有多个,如果有多个,按照先后顺序依次执行
最外层的类不能用static修饰
2. final 的作用
Final可以修饰类,修饰方法,修饰变量。
修饰的类叫最终类。该类不能被继承。
修饰的方法不能被重写。
修饰的变量叫常量,常量必须初始化,一旦初始化后,常量的值不能发生改变。
3. StringBuffer和StringBuilder
StringBuffer是线程安全的,Stringbuilder是非线程安全的。所以Stringbuilder比stringbuffer效率更高,StringBuffer的方法大多都加了synchronized关键字
4. String str=”aaa”,与String str=new String(“aaa”)一样吗?
不一样的。因为内存分配的方式不一样。
第一种,创建的”aaa”是常量,jvm都将其分配在常量池中。
第二种创建的是一个对象,jvm将其值分配在堆内存中。
5 . 什么是线程
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位
6. 线程和进程的区别
线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据
7. Thread的run和start
start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。
8. Runnable 和 Callable
Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的 call() 方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象
9. intterrupted和is Interrupted
Interrupted()* 和 isInterrupted()的主要区别是前者会将中断状态清除而后者不会。Java多线程的中断机制是用内部标识来实现的,调用Thread.interrupt()来中断一个线程就会设置中断标识为true。当中断线程调用静态方法Thread.interrupted()来检查中断状态时,中断状态会被清零。而非静态方法isInterrupted()用来查询其它线程的中断状态且不会改变中断状态标识。简单的说就是任何抛出InterruptedException异常的方法都会将中断状态清零。无论如何,一个线程的中断状态有有可能被其它线程调用中断来改变。
10. 线程池优势
创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限。为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程。从JDK1.5开始,Java API提供了Executor框架让你可以创建不同的线程池。比如单线程池,每次处理一个任务;数目固定的线程池或者是缓存线程池(一个适合很多生存期短的任务的程序的可扩展线程池
11. 线程池的submit和execute
两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中, 而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法
12. wait和sleep
Java程序中wait 和 sleep都会造成某种形式的暂停,它们可以满足不同的需要。wait()方法用于线程间通信,如果等待条件为真且其它线程被唤醒时它会释放锁,而sleep()方法仅仅释放CPU资源或者让当前线程停止执行一段时间,但不会释放锁
13. java程序的编译和运行
Java程序从源文件创建到程序运行要经过两大步骤:
1、源文件由编译器编译成字节码(ByteCode);
2、字节码由java虚拟机解释运行。
因为java程序既要编译同时
也要经过JVM的解释运行,
所以说Java被称为半解释语言
第一步(编译):
创建完源文件之后,
程序先要被JVM中的java编译器
进行编译为.class文件。
java编译一个类时,
如果这个类所依赖的类还没有被编译,
编译器会自动的先编译这个所依赖的类,
然后引用。
如果java编译器在指定的目录下
找不到该类所依赖的类的 .class文件或者 .java源文件,
就会报"Cant found sysbol"的异常错误。
编译后的字节码文件格式
主要分为两部分:
常量池和方法字节码。
常量池记录的是代码出现过的(常量、类名、成员变量等)
以及符号引用(类引用、方法引用,成员变量引用等);
方法字节码中放的是各个方法的字节码。
第二步(运行):
java类运行的过程大概分为两个步骤:
(1)类的加载
(2)类的执行。
需要说明的一点的是:
JVM主要在程序第一次运行时主动使用类的时候,
才会立即去加载。
换言之,
JVM并不是在运行时就会把所有使用到的类
都加载到内存中,
而是用到,不得不加载的时候,
才加载进来,而且只加载一次!
14. & 与 && 的区别
&运算符有两种用法:(1)按位与;(2)逻辑与。&&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true整个表达式的值才是true。&&之所以称为短路运算是因为,如果&&左边的表达式的值是false,右边的表达式会被直接短路掉,不会进行运算
15. short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
short s1 = 1; s1 = s1 + 1; s1+1
运算结果是int型,
需要强制转换类型;
short s1 = 1; s1 += 1;
可以正确编译,自动类型提升。
16. int和Integer
Java 提供两种不同的类型:
引用类型和原始类型(或内置类型);
int是java的原始数据类型,
Integer是java为int提供的封装类。
引用类型和原始类型的行为完全不同,
并且它们具有不同的语义。
引用类型和原始类型具有不同的特征和用法,
它们包括:大小和速度问题,
这种类型以哪种类型的数据结构存储,
当引用类型和原始类型
用作某个类的实例数据时所指定的缺省值。
对象引用实例变量的缺省值为 null,
而原始类型实例变量的缺省值
与它们的类型有关。
17 跳出多重循环
普通的break只能跳出最内层的循环,但在最内层循环使用return会直接返回到最外层;
break 跳出多层循环的可以用label
在最外层循环前加label标识,
然后用break:label方法即可跳出多重循环。
ok:while(true){
while(true){
break ok;
}
}
18. java创建对象的方式
new/反射/clone/序列化
19 String s = new String("xyz");创建了几个String Object
两个,一个字符对象,一个字符对象引用对象
20. Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math.round(11.5)==12;
Math.round(-11.5)==-11;
round方法返回与参数最接近的长整数,
参数加1/2后求其floor
21. swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上
swtich()里面必须是int和enum--即枚举类型。
short、 char 或者 byte他会自动转换为int的。。
long不能自动转换为int..
因为long比int范围大..可能会丢失精度..
在java的1.7之后的jdk版本,
java中的switch里面表达式的类型可以是string类型,
之前是不可以使用的
22 final/finally/finalize
1、final修饰符(关键字)。
被final修饰的类,
就意味着不能再派生出新的子类,
不能作为父类而被子类继承。
因此一个类不能既被abstract声明,
又被final声明。将变量或方法声明为final,
可以保证他们在使用的过程中不被修改。
被声明为final的变量必须在声明时给出变量的初始值,
而在以后的引用中只能读取。
被final声明的方法也同样只能使用,
即不能方法重写。
2 提供finally块来执行任何清除操作。
不管有没有异常被抛出、捕获,finally块都会被执行。
try块中的内容是在无异常时执行到结束。
catch块中的内容,
是在try块内容发生catch所声明的异常时,
跳转到catch块中执行。
finally块则是无论异常是否发生,
都会执行finally块的内容,
所以在代码逻辑中有需要
无论发生什么都必须执行的代码,
就可以放在finally块中。
3、finalize是方法名。
java技术允许使用finalize()方法
在垃圾收集器将对象从内存中
清除出去之前做必要的清理工作。
这个方法是由垃圾收集器
在确定这个对象没有被引用时对这个对象调用的。
它是在object类中定义的,
因此所有的类都继承了它。
子类覆盖finalize()方法以整理系统资源或者被执行其他清理工作。
finalize()方法是在垃圾收集器
删除对象之前对这个对象调用的。
23. 重写的特征
重写的特征:
(1):方法名必须相同,返回值类型必须相同
(2):参数列表必须相同
(3):访问权限不能比父类中被重写的方法的访问权限更低。
例如:如果父类的一个方法被声明为public,
那么在子类中重写该方法就不能声明为protected。
(4):子类和父类在同一个包中,
那么子类可以重写父类所有方法,
除了声明为private和final的方法。
(5):构造方法不能被重写,
简单而言:就是具体的实现类对于父类的该方法实现不满意,
需要自己在写一个满足于自己要求的方法。
24. String StringBuilder StringBuffer
首先说运行速度,或者说是执行速度,
在这方面运行速度快慢为:StringBuilder > StringBuffer > String
String最慢的原因:
String为字符串常量,
而StringBuilder和StringBuffer均为字符串变量,
即String对象一旦创建之后该对象是不可更改的,
但后两者的对象是变量,是可以更改的。
而StringBuilder和StringBuffer的对象是变量,
对变量进行操作就是直接对该对象进行更改,
而不进行创建和回收的操作,
所以速度要比String快很多。
String ----> 字符串常量
StringBuffer ----> 字符串变量(线程安全的)
StringBuilder ----> 字符串变量(非线程安全的)
String:适用于少量的字符串操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
25. 构造器Constructor是否可被override?
构造器Constructor不能被继承,
因此不能重写Overriding,
但可以被重载Overloading
1). 构造器不能是native,final,static,synchronized 的,
可以是public,private,或什么都没有。
2). 构造器函数里可以写return呢,但后面什么都不许有(包括null)
3). 构造器不能返回值.
但如果有个"构造器"返值了,
它就不是构造器喽,只是个普通方法
4). super();this();这两个方法只能在构造方法里调用.
5). 成员变量声明时候赋值,比构造函数还早.
26. error和Exception的区别
27. hashmap hashtable
hashmap:
1.线程不安全
2.允许有null的键和值
3.效率高一点、
4.方法不是Synchronize的要提供外同步
5.有containsvalue和containsKey方法
6.HashMap 是Java1.2 引进的Map interface 的一个实现
7.HashMap是Hashtable的轻量级实现
hashtable:
1.线程安全
2.不允许有null的键和值
3.效率稍低、
4.方法是是Synchronize的
5.有contains方法
6.Hashtable 继承于Dictionary 类
7.Hashtable 比HashMap 要旧
28. == equals区别
对于==,
如果作用于基本数据类型的变量,
则直接比较其存储的
“值”是否相等;
如果作用于引用类型的变量,
则比较的是所指向的对象的地址
对于equals方法,
注意:equals方法不能作用于基本数据类型的变量
如果没有对equals方法进行重写,
则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,
比较的是所指向的对象的内容。
29. 静态变量和实例变量的区别
静态变量也叫类变量,
这种变量前加了static修饰符。
可以直接用类名调用,
也可以用对象调用,
而且所有对象的同一个类变量
都是共享同一块内存空间。
实例变量也叫对象变量,
这种变量没有加static修饰符。
只能通过对象调用,
而且所有对象的同一个实例变量
是共享不同的内存空间的。
区别在于:
静态变量是所有对象共有的,
某一个对象将它的值改变了,
其他对象再去获取它的值,
得到的是改变后的值;
实例变量则是每一个对象私有的,
某一个对象将它的值改变了,
不影响其他对象取值的结果,
其他对象仍会得到实例变量
一开始就被赋予的值。
实例变量必须创建对象后
才可以通过这个对象来使用,
静态变量
则可以直接使用类名来引用。
31. 垃圾收集的基本原理
垃圾回收器是Java平台中用的
最频繁的一种对象销毁方法。
垃圾回收器会全程侦测Java应用程序的运行情况。
当发现有些对象成为垃圾时,
垃圾回收器就会销毁这些对象,
并释放这些对象所占用的内存空间。
在这里,程序开发人员需要知道,
在哪些情况下垃圾回收器
会认为这些对象是垃圾对象。
通常情况下,如果发生以下两种情况时,
系统会认为这些对象是垃圾对象,
需要销毁。
一是将一个NULL值赋值给对象。
二是对象其超出了作用范围,
32. 有什么办法主动通知虚拟机进行垃圾回收?
对于GC来说,
当程序员创建对象时,
GC就开始监控这个对象的地址、
大小以及使用情况。
通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。
通过这种方式确定哪些对象是”可达的”,
哪些对象是”不可达的”。
当GC确定一些对象为”不可达”时,
GC就有责任回收这些内存空间。
可以。程序员可以手动执行System.gc(),
通知GC运行,
但是Java语言规范
并不保证GC一定会执行。
System.gc()的工作原理
Java中的内存分配
是随着new一个新的对象来实现的,
这个很简单,
而且也还是有一些
可以“改进”内存回收的机制的,
其中最显眼的
就是这个System.gc()函数。
乍一看这个函数似乎是可以进行垃圾回收的,
可事实并不是那么简单。
其实这个gc()函数的作用只是提醒虚拟机:
程序员希望进行一次垃圾回收。
但是它不能保证垃圾回收一定会进行,
而且具体什么时候进行
是取决于具体的虚拟机的,
不同的虚拟机有不同的对策。
33. 内部类的一些规则
完全可以。
如果不是静态内部类,
那没有什么限制!
一个内部类对象可以访问
创建它的外部类对象的成员包括私有成员。
如果你把静态嵌套类当作内部类的一种特例,
那在这种情况下不可以访问外部类的
普通成员变量,
而只能访问外部类中的静态成员。
内部类的访问规则:
1、内部类可以直接访问外部类中的成员,
包括私有。
之所以可以直接访问外部类中的成员,
是因为内部类中持有了
一个外部类的引用,
格式 外部类名.this
2、外部类要访问内部类,必须建立内部类对象。
内部类定义在局部时,
1、不可以被成员修饰符修饰
2、可以直接访问外部类中的成员,
因为还持有外部类中的引用。
但是不可以访问它所在的局部中的变量。
只能访问被final修饰的局部变量。
34. 异常
一、Execption可以分为
java标准定义的异常
程序员自定义异常2种
1.一种是当程序违反了java语规则的时候,
JAVA虚拟机就会将发生的错误
表示为一个异常.
这里语法规则指的是
JAVA类库内置的语义检查。
例如 int i = 2 / 0
或者 String str = null;str.length();
2.另一种情况就是JAVA允许程序员
扩展这种语义检查,
程序员可以创建自己的异常,
并自由选择在何时用throw关键字
引发异常。
例如 Exception ex = new Exception("这是我自定义的异常;
throw ex;
所有的异常都是Thowable的子类。
异常处理是与程序执行是并行的。
二、异常的处理方式
1.捕获异常
try {
int i = 2 / 0;
} catch (Exception ex) {
ex.printStackTrace();
System.out.println("异常信息:" + ex.getMessage());
}
2.上抛异常 throws
public void test() throws Exception {
String str = null;
str.length();
}
35. 运行时异常和非运行时异常
(1)运行时异常
都是RuntimeException类
及其子类异常,
如NullPointerException、
IndexOutOfBoundsException等,
这些异常是不检查异常,
程序中可以选择捕获处理,
也可以不处理。
这些异常一般是由程序逻辑错误引起的,
程序应该从逻辑角度
尽可能避免这类异常的发生。
当出现RuntimeException的时候,
我们可以不处理。
当出现这样的异常时,
总是由虚拟机接管。
比如:我们从来没有人
去处理过NullPointerException异常,
它就是运行时异常,
并且这种异常还是最常见的异常之一。
出现运行时异常后,
系统会把异常一直往上层抛,
一直遇到处理代码。
如果没有处理块,
到最上层,
如果是多线程就由Thread.run()抛出,
如果是单线程就被main()抛出。
抛出之后,
如果是线程,
这个线程也就退出了。
如果是主程序抛出的异常,
那么这整个程序也就退出了。
运行时异常是Exception的子类,
也有一般异常的特点,
是可以被Catch块处理的。
只不过往往我们不对他处理罢了。
也就是说,
你如果不对运行时异常进行处理,
那么出现运行时异常之后,
要么是线程中止,
要么是主程序终止。
如果不想终止,
则必须扑捉所有的运行时异常,
决不让这个处理线程退出。
队列里面出现异常数据了,
正常的处理应该是把异常数据舍弃,
然后记录日志。
不应该由于异常数据
而影响下面对正常数据的处理。
(2)非运行时异常
是RuntimeException以外的异常,
类型上都属于Exception类及其子类。
如 IOException、SQLException 等
以及用户自定义的Exception异常。
对于这种异常,
JAVA编译器强制要求我们
必需对出现的这些异常进行catch并处理,
否则程序就不能编译通过。
所以,面对这种异常不管我们是否愿意,
只能自己去写一大堆catch块
去处理可能的异常。
36. Comparable和Comparator
37. hashcode和equals方法
Java中的HashMap使用
hashCode()和equals()方法
来确定键值对的索引,
当根据键获取值的时候
也会用到这两个方法。
如果没有正确的实现这两个方法,
两个不同的键可能会有相同的hash值,
因此可能会被集合认为是相等的。
而且,这两个方法也用来发现重复元素,
所以这两个方法的实现对HashMap的
精确性和正确性是至关重要的。
同一个对象(没有发生过修改)
无论何时调用hashCode(),
得到的返回值必须一样。
hashCode()返回值相等,
对象不一定相等,
通过hashCode()和equals()
必须能唯一确定一个对象。
一旦重写了equals(),
就必须重写hashCode()。
而且hashCode()生成哈希值的依据应该是
equals()中用来比较是否相等的字段。
如果两个由equals()规定相等的对象
生成的hashCode不等,
对于HashMap来说,
他们可能分别映射到不同位置,
没有调用equals()比较是否相等的机会,
两个实际上相等的对象可能被插入到不同位置,
出现错误。
其他一些基于哈希方法的集合类
可能也会有这个问题。
怎么判断两个对象是相同的?
使用等号== 判断两个对象是否相同,
这种是严格的相同,
即内存中的同一个对象
Object的equal方法就是使用==判断两个对象是否相同
集合set要求元素是唯一的,怎么实现?
要实现元素的唯一,
需要在往集合set中添加元素时,
判断集合set是否存在相同的元素,
如果存在,则不添加,反之。
那么怎么确定两个元素是否相同,
1.如果是使用等号==判断两个元素是否相同,
即默认使用Object的equals的方法。
2.如果没有使用等号==判断两个元素是否相同,
而是按照某种业务规则判断两个元素是否相同,
即重写了Object的equals的方法。
当重写equals方法,必须重写hashCode方法吗?
不是必须的,
得看具体的情况
当equals方法返回的结果和使用等号
比较的结果是一致的时候,
是没有必要重写hashCode方法。
当用等号比较对象,
只有是内存中同一个对象实例,
才会返回true,
当然调用其hashCode()方法
肯定返回相同的值,
这满足了满足了hashCode的约束条件,
所以不用重写hashCode()方法。
当equals方法返回的结果
和使用等号比较的结果是不一致的时候,
就需要重写hashCode方法。
当重写后的equals方法
不认为只有是在内存中同一个对象实例,
才返回true,
如果不重新hashCode方法()
Object的hashCode()方法 是对内存地址的映射,
hashCode方法返回的值肯定是不同的,
这违背了hashCode的约束条件,
所以必须要重新hashCode方法,
并满足对hashCode的约束条件。
38. 并发修改异常
什么是并发修改异常:
当我们在遍历实现了collection接口
与iterator接口的集合时(List、Set、Map),
我们可以通过遍历索引
也可以通过迭代器进行遍历。
在我们使用迭代器进行遍历集合的时候,
会获取到当前集合的迭代对象。
在里面有封装了迭代器的remove方法
与集合自带的remove方法,
如果我们调用迭代器对象的remove方法
是没问题的,
但是当我们调用集合自带的remove方法时,
就会产生ConcurrentModificationException
并发修改异常。
也就是说,
当我们通过迭代器进行遍历集合的时候,
是不允许集合本身在结构上发生变化的。
19 。CopyOnWriteList
其原理大概可以通俗的理解为:
初始化的时候只有一个容器,
很常一段时间,
这个容器数据、
数量等没有发生变化的时候,
大家(多个线程),都是读取
假设这段时间里只发生读取的操作
同一个容器中的数据,
所以这样大家读到的数据都是
唯一、一致、安全的,
但是后来有人往里面增加了一个数据,
这个时候CopyOnWriteArrayList 底层实现
添加的原理是先copy出一个容器
可以简称副本,
再往新的容器里添加这个新的数据,
最后把新的容器的引用地址
赋值给了之前那个旧的的容器地址,
但是在添加这个数据的期间,
其他线程如果要去读取数据,
仍然是读取到旧的容器里的数据。
40. 多态机制
靠的是父类或接口的
引用指向子类或实现类的对象,
调用的方法是内存中
正在运行的那个对象的方法。
Java实现多态有三个必要条件:
继承、
重写、
向上转型。
继承:
在多态中必须存在
有继承关系的子类和父类。
重写:
子类对父类中某些方法进行重新定义,
在调用这些方法时
就会调用子类的方法。
向上转型:
在多态中需要将子类的引用
赋给父类对象,
只有这样该引用才能够具备
技能调用父类的方法和子类的方法。
只有满足了上述三个条件,
我们才能够在同一个继承结构中
使用统一的逻辑实现代码处理不同的对象,
从而达到执行不同的行为。
多态机制遵循的原则概括为
当超类对象引用变量引用子类对象时,
被引用对象的类型
而不是引用变量的类型
决定了调用谁的成员方法,
但是这个被调用的方法
必须是在超类中定义过的,
也就是说被子类覆盖的方法,
但是它仍然要根据继承链中
方法调用的优先级来确认方法,
该优先级为:
this.method(O)、
super.method(O)、
this.method((super)O)、
super.method((super)O)。
41. 局部变量和成员变量的区别
成员变量与局部变量的区别
1、在类中的位置不同
成员变量:
在类中方法外面
局部变量:
在方法或者代码块中,
或者方法的声明上
2、在内存中的位置不同,
成员变量:在堆中(方法区中的静态区)
局部变量:在栈中
3、生命周期不同
成员变量:
随着对象的创建而存在,
随着对象的消失而消失
局部变量:
随着方法的调用或者代码块的执行
而存在,
随着方法的调用完毕或者
代码块的执行完毕而消失
4、初始值
成员变量:
有默认初始值
局部变量:
没有默认初始值,
使用之前需要赋值,
否则编译器会报错
42. Comparable和Comparator
这两种比较器Comparable和Comparator,后者相比前者有如下优点:
个性化比较:如果实现类没有实现Comparable接口,又想对两个类进行比较(或者实现类实现了Comparable接口,但是对compareTo方法内的比较算法不满意),那么可以实现Comparator接口,自定义一个比较器,写比较算法。
解耦:实现Comparable接口的方式比实现Comparator接口的耦合性要强一些,如果要修改比较算法,要修改Comparable接口的实现类,而实现Comparator的类是在外部进行比较的,不需要对实现类有任何修改。从这个角度说,其实有些不太好,尤其在我们将实现类的.class文件打成一个.jar文件提供给开发者使用的时候。
41 String 相关
1、String是基本数据类型吗?
String不是基本数据类型。
2、String是可变的话?
String是final类型的,不可变。
3、怎么比较两个字符串的值一样,怎么比较两个字符串是否同一对象?
比较字符串的值是否相同用equals,比较字符串对象是否同一个用==。
4、switch中可以使用String吗?
在java中switch后的表达式的类型只能为以下几种:byte、short、char、int(在Java1.6中是这样),在java1.7后支持了对string的判断。
5、String str = new String("abc");创建了几个对象,为什么?
创建了两个,"abc"本身创建在常量池,通过new又创建在堆中引用。
6、String、StringBuffer、StringBuilder有什么区别?
String、StringBuffer、StringBuilder最大的不同是String不可变,后者可变。StringBuffer是线程安全的,StringBuilder线程不安全速度较快。
7、String.trim()方法去掉的是哪些字符?
trim去掉字符串首尾的空白字符。
8、String可以被子类继承吗?
既然String是final的,所以不能被继承。
9、可以自定义java.lang.String类并使用吗?
可以自定义java.lang.String类并编译成功,但不能被加载使用,具体请学习类加载机制。
10、String与byte[]两者相互之间如何转换?
String > byte[] 通过String类的getBytes方法;byte[] > String通过new String(byte[])构造器。
public static void main(String[] args) {
String a = "a1";
String b = "a" + 1;
System.out.println(a == b ); //true
}
String x = "abc";
String y = new String("abcd");
x与y存在栈中,它们保存了相应对象的引用。第一条语句没有在堆中分配内存,而是将“abc”保存在常量池中。对于第二条语句,同样会在常量池中有一个“abcd”的字符串,当new时,会拷贝一份该字符串存放到堆中,于是y指向了堆中的那个“abcd”字符串
当intern()方法被调用,如果字符串池中含有一个字符串和当前调用方法的字符串eqauls相等,那么就会返回池中的字符串。如果池中没有的话,则首先将当前字符串加入到池中,然后返回引用。
https://blog.csdn.net/chj97/article/details/6899598