1、String,buffer,build,越往后效率越高,越不安全(jdk版本更新规律)

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象
StringBuilder 类在 1.5 中被提出, StringBuffer( 1.2)安全(因为StringBuffer中很多方法可以带有synchronized), StringBuilder线程不安全(不能同步访问)。
StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
在应用程序要求线程安全的情况下,则必须使用 StrinnBuffer 类。

2、java中实例化(创建)对象有哪几种方式

1.用new 创建对象,这是最常用的创建对象的方法。
2.运用反射,调用Java.lang.Class或者java.lang.reflect.Constructor类的newInstance()实例方法。
3.调用对象的clone()方法
clone()表示克隆,使用这个实例化一个对象的前提是:前面已经有一个实例化过的对象
4.运用反序列化手段,调用java.io.ObjectInputStream对象的readObject()方法

3、String常用类

1. length()字符串的长度
2.equals()和equalsIgnoreCase()比较两个字符串是否相等,前者区分大小写,后者不区分
String a = “Hello Word”; String b = “hello word”; System.out.println(a.equals(b));
System.out.println(a.equalsIgnoreCase(b));
输出的结果为第一条为false,第二条为true。
3.startsWith()和endsWith()判断字符串是不是以特定的字符开头或结束
String a = “Hello Word”; System.out.println(a.startsWith(“ee”)); System.out.println(a.endsWith(“rd”));
输出的结果第一条为false,第二条为true。
4. toUpperCase()和toLowerCase()将字符串转换为大写或小写
String a = “Hello Word”; System.out.println(a.toUpperCase()); System.out.println(a.toLowerCase());
输出的结果第一条为“HELLO WORD”,第二条为“hello word”。
5. concat() 连接两个字符串
String a = “Hello Word”; String b = “你好”; System.out.println(b.concat(a));
输出的结果为“你好Hello Word”。
6. substring()截取字符串
String a = “Hello Word”; System.out.println(a.substring(0, 5)); System.out.println(a.substring(6));
输出的结果第一条为“Hello”,第一个参数0(beginIndex)是开始截取的位置,第二个参数5(endIndex)是截取结束的位置,输出的结果第二条是“Word”,参数6(beginIndex)是开始截取的位置。
7.replace() 替换
String a = “Hello Word”; String b = “你好”; System.out.println(a.replace(a, b)); System.out.println(a.replace(a, “HELLO WORD”));
System.out.println(b.replace(“你”, “大家”));
输出的结果第一条为“你好”,第二条为“HELLO WORD”,第三条为“大家好”。

4、map集合遍历

  1. Map <String , String > map = new HashMap <String , String >();
  2. map.put("20", "120");
  3. map.put("30", "130");
  4. map.put("40", "140");
  5. map.put("10", "100");
  6. map.put("50", "150");

1.方式一用于获取所有的键(key)

  1. Set<String> map1 = map.keySet();
  2. for(String key : map1) {
  3. System.out.println(map.get(key));//可以获取key 和values,不加map.get(key)就是遍历Key
  4. }

2.方式二用于获取所有的值(values)

  1. Collection<String> volues = map.values();
  2. for(String e : volues) {
  3. System.out.println(e);
  4. }

3.方式三用于获取所有的条目(项)Entry

  1. Set<Entry<String , String >> map4 = map.entrySet();//这是一个为项类型的键,返回值也是键,下面的变量数据类型就是Entry<String,String>
  2. //Collection是不行的 Collection<Entry<String ,String>> map6= map.values();
  3. for(Entry <String ,String> map5: map4) {
  4. System.out.println(map5);
  5. System.out.println(map5.getKey() +"\t" +map5.getValue());
  6. // 50=150
  7. // 40=140
  8. // 30=130
  9. // 20=120
  10. // 10=100
  11. }

4.方式四用于获取到entrySet(),然后用迭代器取出元素(iterator)

  1. Iterator<Entry<String ,String>> map6 = map.entrySet().iterator();
  2. while(map6.hasNext()) {
  3. System.out.println(map6.next());
  4. }

5.方式五用于获取到key,然后用迭代器取出键(iterator)

  1. Iterator<String> map7 = map.keySet().iterator();
  2. while(map7.hasNext()) {
  3. //String key = map8.next();这一行正常情况下不需要,当输出语句里面有两个Next时候加上,只用同一个next指针指,不会next+1指第二个
  4. System.out.println(map7.next());
  5. }

6.方式五用于获取到values,然后用迭代器取出值(iterator)

  1. Iterator<String> map8 = map.values().iterator();
  2. while(map8.hasNext()) {
  3. System.out.println(map8.next());
  4. }
  5. }

5、值传递,引用传递

  • 8种基本数据类型都是值传递,String类型是特殊的引用数据类型,作为参数传递值不会改变
  • 引用数据类型都是引用传递,
  • 值传递不会改变原参数的值,因为传递的是值的拷贝
  • 引用传递会改变原参数的值,因为传递的是地址

值传递:就是将该值的副本传过去(基本数据类型+String类型的传递,就是按值传递)
引用传递:就是将值的内存地址传过去(除基本数据类型+String以外类型的传递,就是引用传递)引用数据类型分3种:类,接口,数组;

6、= 和= =的区别

“=” 赋值,
“= =”当比较基本数据类型的时候,判断前后两个值是否相等;
当比较引用数据类型的时候,判断= =前后两个值的内存地址是否相等;
区别:
= :为赋值表达式 = = :为逻辑表达式

7、变量类型

实例变量: 类中定义的变量,即类成员变量,如果没有初始化,会有默认值;
局部变量: 在方法中定义的变量,必须初始化;
类变量: 用static修饰的属性;
final变量: 用final 修饰的变量,

8、接口和抽象类

抽象类(abstract) 接口(interface)
方法 普通方法,静态方法,抽象方法(可以为0||N)构造方法,普通属性 1.7 常量,抽象方法 1.8 默认方法,静态方法(没有构造)
子类 只能继承一个抽象类,抽象方法必须重写 可以实现多个接口,抽象方法必须重写,除非定义abstract
方法访问类型 可以是public,protected, 1.8之前默认public abstract,可以不写
成员变量 各种类型 只能是public static final类型
JDK1.8的接口对于JDK1.7的变化: 添加了static或者仅用default(不可省略)修饰的非抽象方法.

类与类之间是继承,并且是单继承(extends)

接口与接口之间是继承,并且是多继承(extends)

类与接口之间是实现,并且是多实现(implements)

注意:接口不能继承类

如果一个类既有继承也有实现,则继承必须位于实现的前面。

9、创建对象的几种方式

  1. new关键字

通过这种方式我们还可以调用任意的构造器(无参的和有参的)。

  1. public class Main {
  2. public static void main(String[] args) {
  3. Person person1 = new Person();
  4. Person person2 = new Person("fsx", 18);
  5. }
  6. }
  1. Class.newInstance

反射创建对象时最常用的方法
Class类的newInstance使用的是类的public的无参构造器。因此也就是说使用此方法创建对象的前提是必须有public的无参构造器才行,否则报错如下:

  1. // 没无参构造器报错信息
  2. Caused by: java.lang.NoSuchMethodException: com.fsx.bean.Person.<init>()
  3. at java.lang.Class.getConstructor0(Class.java:3082)
  4. at java.lang.Class.newInstance(Class.java:412)
  5. ... 1 more
  6. // 无参构造器不是public的报错信息
  7. Exception in thread "main" java.lang.IllegalAccessException: Class com.fsx.maintest.Main can not access a member of class com.fsx.bean.Person with modifiers "private"
  8. at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
  9. at java.lang.Class.newInstance(Class.java:436)
  10. at com.fsx.maintest.Main.main(Main.java:13)

正常使用

  1. public class Main {
  2. public static void main(String[] args) throws Exception {
  3. Person person = Person.class.newInstance();
  4. System.out.println(person); // Person{name='null', age=null}
  5. }
  6. }
  1. Constructor.newInstance

本方法和Class类的newInstance方法很像,但是比它强大很多。 java.lang.relect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数(不再必须是无参)的和私有的构造函数(不再必须是public)

  1. public class Main {
  2. public static void main(String[] args) throws Exception {
  3. // 包括public的和非public的,当然也包括private的
  4. Constructor<?>[] declaredConstructors = Person.class.getDeclaredConstructors();
  5. // 只返回public的~~~~~~(返回结果是上面的子集)
  6. Constructor<?>[] constructors = Person.class.getConstructors();
  7. Constructor<?> noArgsConstructor = declaredConstructors[0];
  8. Constructor<?> haveArgsConstructor = declaredConstructors[1];
  9. noArgsConstructor.setAccessible(true); // 非public的构造必须设置true才能用于创建实例
  10. Object person1 = noArgsConstructor.newInstance();
  11. Object person2 = declaredConstructors[1].newInstance("fsx", 18);
  12. System.out.println(person1);
  13. System.out.println(person2);
  14. }
  15. }
  16. 输出:
  17. Person{name='null', age=null}
  18. Person{name='fsx', age=18}
  1. Clone方法

无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面的对象的内容全部拷贝进去,用clone方法创建对象并不会调用任何构造函数。 要使用clone方法,我们必须先实现Cloneable接口并复写Object的clone方法(因为Object的这个方法是protected的,你若不复写,外部也调用不了呀)。

  1. public class Person implements Cloneable {
  2. ...
  3. // 访问权限写为public,并且返回值写为person
  4. @Override
  5. public Person clone() throws CloneNotSupportedException {
  6. return (Person) super.clone();
  7. }
  8. ...
  9. }
  10. public class Main {
  11. public static void main(String[] args) throws Exception {
  12. Person person = new Person("fsx", 18);
  13. Object clone = person.clone();
  14. System.out.println(person);
  15. System.out.println(clone);
  16. System.out.println(person == clone); //false
  17. }
  18. }
  19. 输出结果:
  20. Person{name='fsx', age=18}
  21. Person{name='fsx', age=18}
  22. false
  1. 反序列化

当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象,在反序列化时,JVM创建对象并不会调用任何构造函数
为了反序列化一个对象,我们需要让我们的类实现Serializable接口。

  1. public class Main {
  2. public static void main(String[] args) throws Exception {
  3. Person person = new Person("fsx", 18);
  4. byte[] bytes = SerializationUtils.serialize(person);
  5. // 字节数组:可以来自网络、可以来自文件(本处直接本地模拟)
  6. Object deserPerson = SerializationUtils.deserialize(bytes);
  7. System.out.println(person);
  8. System.out.println(deserPerson);
  9. System.out.println(person == deserPerson);
  10. }
  11. }
  12. 输出:
  13. Person{name='fsx', age=18}
  14. Person{name='fsx', age=18}
  15. false
  16. 备注:JDK序列化、反序列化特别特别耗内存。据我测试单单一个如上的Person对象的反序列化,2MJVM内存都还不够…
创建对象方式 是否调用了构造器
new关键字
Class.newInstance
Constructor.newInstance
Clone
反序列化

7、常见的运行异常runtime exception。

NullPointerException 空指针异常;

ClassCastException 强制转换类型异常;

IndexOutOfBounsExcption 下标越界异常;

NumberFormatException 数字格式异常;

8.是否可以继承String类。

在Java中,string类的修饰符是final,这意味着string类是不可继承和修改的。

9、异常之try、catch、final

try{}里有一个return语句,紧跟在try后的finally里的code会不会被执行,什么时候执行,return前执行还是return后执行。
try里面有return语句,无论try里面是否有捕获异常。finally中的代码都会执行,并且是在return前执行,如果finally也有return语句的话,程序会在finally直接return,而不会在try里面return。

10、Java中有几种类型流

Java中有两种类型的流,分为为字节流和字符流,每种流都由输入和输出,共有四种抽象类以供继承,分别为InputStream,OutputStream,Reader,Writer。
字节流可以用来处理任何对象,包括二进制对象,而字符流只能用来处理字符
字符流处理的单元为两个字节的Unicode字符,而字节流处理的单元为一个字节。