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集合遍历
Map <String , String > map = new HashMap <String , String >();
map.put("20", "120");
map.put("30", "130");
map.put("40", "140");
map.put("10", "100");
map.put("50", "150");
1.方式一用于获取所有的键(key)
Set<String> map1 = map.keySet();
for(String key : map1) {
System.out.println(map.get(key));//可以获取key 和values,不加map.get(key)就是遍历Key
}
2.方式二用于获取所有的值(values)
Collection<String> volues = map.values();
for(String e : volues) {
System.out.println(e);
}
3.方式三用于获取所有的条目(项)Entry
Set<Entry<String , String >> map4 = map.entrySet();//这是一个为项类型的键,返回值也是键,下面的变量数据类型就是Entry<String,String>
//Collection是不行的 Collection<Entry<String ,String>> map6= map.values();
for(Entry <String ,String> map5: map4) {
System.out.println(map5);
System.out.println(map5.getKey() +"\t" +map5.getValue());
// 50=150
// 40=140
// 30=130
// 20=120
// 10=100
}
4.方式四用于获取到entrySet(),然后用迭代器取出元素(iterator)
Iterator<Entry<String ,String>> map6 = map.entrySet().iterator();
while(map6.hasNext()) {
System.out.println(map6.next());
}
5.方式五用于获取到key,然后用迭代器取出键(iterator)
Iterator<String> map7 = map.keySet().iterator();
while(map7.hasNext()) {
//String key = map8.next();这一行正常情况下不需要,当输出语句里面有两个Next时候加上,只用同一个next指针指,不会next+1指第二个
System.out.println(map7.next());
}
6.方式五用于获取到values,然后用迭代器取出值(iterator)
Iterator<String> map8 = map.values().iterator();
while(map8.hasNext()) {
System.out.println(map8.next());
}
}
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、创建对象的几种方式
- new关键字
通过这种方式我们还可以调用任意的构造器(无参的和有参的)。
public class Main {
public static void main(String[] args) {
Person person1 = new Person();
Person person2 = new Person("fsx", 18);
}
}
- Class.newInstance
反射创建对象时最常用的方法
Class类的newInstance使用的是类的public的无参构造器。因此也就是说使用此方法创建对象的前提是必须有public的无参构造器才行,否则报错如下:
// 没无参构造器报错信息
Caused by: java.lang.NoSuchMethodException: com.fsx.bean.Person.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 1 more
// 无参构造器不是public的报错信息
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"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.Class.newInstance(Class.java:436)
at com.fsx.maintest.Main.main(Main.java:13)
正常使用
public class Main {
public static void main(String[] args) throws Exception {
Person person = Person.class.newInstance();
System.out.println(person); // Person{name='null', age=null}
}
}
- Constructor.newInstance
本方法和Class类的newInstance方法很像,但是比它强大很多。 java.lang.relect.Constructor类里也有一个newInstance方法可以创建对象。我们可以通过这个newInstance方法调用有参数(不再必须是无参)的和私有的构造函数(不再必须是public)。
public class Main {
public static void main(String[] args) throws Exception {
// 包括public的和非public的,当然也包括private的
Constructor<?>[] declaredConstructors = Person.class.getDeclaredConstructors();
// 只返回public的~~~~~~(返回结果是上面的子集)
Constructor<?>[] constructors = Person.class.getConstructors();
Constructor<?> noArgsConstructor = declaredConstructors[0];
Constructor<?> haveArgsConstructor = declaredConstructors[1];
noArgsConstructor.setAccessible(true); // 非public的构造必须设置true才能用于创建实例
Object person1 = noArgsConstructor.newInstance();
Object person2 = declaredConstructors[1].newInstance("fsx", 18);
System.out.println(person1);
System.out.println(person2);
}
}
输出:
Person{name='null', age=null}
Person{name='fsx', age=18}
- Clone方法
无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面的对象的内容全部拷贝进去,用clone方法创建对象并不会调用任何构造函数。 要使用clone方法,我们必须先实现Cloneable接口并复写Object的clone方法(因为Object的这个方法是protected的,你若不复写,外部也调用不了呀)。
public class Person implements Cloneable {
...
// 访问权限写为public,并且返回值写为person
@Override
public Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
...
}
public class Main {
public static void main(String[] args) throws Exception {
Person person = new Person("fsx", 18);
Object clone = person.clone();
System.out.println(person);
System.out.println(clone);
System.out.println(person == clone); //false
}
}
输出结果:
Person{name='fsx', age=18}
Person{name='fsx', age=18}
false
- 反序列化
当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象,在反序列化时,JVM创建对象并不会调用任何构造函数。
为了反序列化一个对象,我们需要让我们的类实现Serializable接口。
public class Main {
public static void main(String[] args) throws Exception {
Person person = new Person("fsx", 18);
byte[] bytes = SerializationUtils.serialize(person);
// 字节数组:可以来自网络、可以来自文件(本处直接本地模拟)
Object deserPerson = SerializationUtils.deserialize(bytes);
System.out.println(person);
System.out.println(deserPerson);
System.out.println(person == deserPerson);
}
}
输出:
Person{name='fsx', age=18}
Person{name='fsx', age=18}
false
备注:JDK序列化、反序列化特别特别耗内存。据我测试单单一个如上的Person对象的反序列化,2M的JVM内存都还不够…
创建对象方式 | 是否调用了构造器 |
---|---|
new关键字 | 是 |
Class.newInstance | 是 |
Constructor.newInstance | 是 |
Clone | 否 |
反序列化 | 否 |
7、常见的运行异常runtime exception。
NullPointerException 空指针异常;
ClassCastException 强制转换类型异常;
IndexOutOfBounsExcption 下标越界异常;
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字符,而字节流处理的单元为一个字节。