java中需要注意的点:
1、java中char类型占用2个字节。
2、返回类型不是方法的签名,即不允许两个只有返回类型不同的方法。
3、String类中使用private final char[] value
存储字符串,所以不可变。Java9之后使用private final byte[] value
4、StringBuilder线程不安全,速度较快;StringBuffer线程安全,使用了同步锁
5、静态方法中无法使用非静态变量。
6、子类使用super()调用父类构造函数,如果没有指定,则会默认执行无参构造函数,如果父类定义了有参构造函数未定义无参构造函数,则会编译错误。
7、成员变量如果未赋予初值,会自动赋予默认值;局部变量不会自动赋值。被final修饰的需要显示赋值。成员变量放在堆内存,局部变量放在栈内存。
8、对象引用存放在栈内存中,对象实例存放在堆内存中。
9、java不可以通过方法将一个引用指向另一个实例对象。
10、foreach循环不能修改集合中的元素。应该是由于值传递。如果要循环修改数据,使用for循环。
11、Comparable接口方法为compareTo(),如TreeMap排序规则是使用对象默认的compareTo()方法,所以改变TreeMap排序规则可以通过重写该方法实现。Comparator接口一般是作为排序函数的参数。
12、接口和抽象类的区别:(1)接口的默认方法是public,所有方法不可以实现,而抽象类可以有非抽象方法;(2)接口中除了static、final变量,不能有其他变量,而抽象类不一定;(3)一个类可以实现多个接口,而抽象类中则不一定;(4)接口方法的默认修饰符为public,抽象方法可以有public,protected和default修饰符,不可以用private修饰;(5)抽象是对类的抽象,而接口是对行为的抽象,是一种行为的规范。jdk8中接口也可以定义静态方法,jdk9的接口可以定义私有方法。
13、final关键字总结:(1)修饰基本数据类型的变量,则其数值在初始化之后不可以改变;如果为引用类型的变量,则初始化之后不能再让其指向另一个对象。(2)final修饰的类不可以被继承,final类中的所有成员方法都会被隐式地指定为final方法;
14、异常处理不会执行finally语句的情况:(1)finally语句执行第一行就发生异常,其他行出现问题,还是得到执行;(2)前面的代码执行了System.exit(int)已退出了程序;若该语句在异常之后,仍会执行;(3)程序所在的线程死亡;(4)关闭CPU。
15、transient关键字修饰的变量无法被序列化。
16、获取键盘输入的常用方式:
1、通过Scanner
Scanner input = new Scanner(System.in);
String s = input.nextLine();
input.close();
2、通过BufferedReader
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
17、为什么有了字节流,还要有字符流?
字符流是由 Java 虚拟机将字节转换得到的,问题就出在这个过程还算是非常耗时,并且,如果我们不知道编码类型就很容易出现乱码问题。所以, I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。
18、深拷贝和浅拷贝
(1)浅拷贝是对基本数据类型进行值传递,对引用数据类型进行引用传递的拷贝;
(2)深拷贝是对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容。
19、equals方法
equals方法容易出现空指针异常,应使用常量或确定值的对象来调用equals。更推荐使用java.util.Objects#equals
Objects.equals(null,"yasuo") //false
20、当使用自动装箱方式创建一个Integer对象时,当数值在-128~127时,将创建的对象缓存起来。内存只保存一份数据。(对象==会比较内存地址)
Integer x=3;
Integer y=3;
System.out.println(x == y);// true
Integer a = new Integer(3);
Integer b = new Integer(3);
System.out.println(a == b);//false
System.out.println(a.equals(b));//true
Integer a = 1234;
Integer b = 1234;
System.out.println(a==b);//false
21、浮点数计算和比较应该使用BigDecimal,在使用BigDecimal时,为了防止精度丢失,推荐使用它的 BigDecimal(String) 构造方法来创建对象。
22、Arrays.asList()
将一个数组转化为List集合,但是转化后其底层还是数组,不可以使用修改集合的方法(add/remove/clear)
/**
*返回由指定数组支持的固定大小的列表。此方法作为基于数组和基于集合的API之间的桥梁,
与Collection.toArray()结合使用。返回的List是可序列化并实现RandomAccess接口。
*/
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
Arrays.asList()体现的是适配器模式,只是转换接口,后台的数据仍是数组。
注意:该方法是泛型方法,传入的对象必须是对象数组。
int[] myArray = { 1, 2, 3 };
List myList = Arrays.asList(myArray);
System.out.println(myList.size());//1
System.out.println(myList.get(0));//数组地址值
System.out.println(myList.get(1));//报错:ArrayIndexOutOfBoundsException
int [] array=(int[]) myList.get(0);
System.out.println(array[0]);//1
当传入一个原生数据类型数组时,Arrays.asList()
的真正得到的参数就不是数组中的元素,而是数组对象本身!此时List 的唯一元素就是这个数组,这也就解释了上面的代码。可以用包装类型解决上述问题。
Arrays.asList()
方法返回的并不是 java.util.ArrayList
,而是 java.util.Arrays
的一个内部类,这个内部类并没有实现集合的修改方法或者说并没有重写这些方法。
List myList = Arrays.asList(1, 2, 3);
System.out.println(myList.getClass());//class java.util.Arrays$ArrayList
23、正确的将数组转换为ArrayList:
List list = new ArrayList<>(Arrays.asList("a","b","c"));
//使用java8的stream
Integer[] myArray = {1,2,3};
List myList = Arrays.stream(myArray).collect(Collectors.toList());
//基本类型也可以实现转换(依赖boxed的装箱操作)
int[] myArray2 = {1,3,2};
List myList = Arrays.stream(myArray2).boxed().collect(Collectors.toList());
//使用 Guava
//对于不可变集合,你可以使用ImmutableList类及其of()与copyOf()工厂方法:(参数不能为空)
List<String> il = ImmutableList.of("string", "elements"); // from varargs
List<String> il = ImmutableList.copyOf(aStringArray); // from array
//对于可变集合,你可以使用Lists类及其newArrayList()工厂方法:
List<String> l1 = Lists.newArrayList(anotherListOrCollection); // from collection
List<String> l2 = Lists.newArrayList(aStringArray); // from array
List<String> l3 = Lists.newArrayList("or", "string", "elements"); // from varargs
//使用 Apache Commons Collections
List<String> list = new ArrayList<String>();
CollectionUtils.addAll(list, str);
24、Collection.toArray()
该方法是一个泛型方法:<T> T[] toArray(T[] a);
如果toArray
方法中没有传递任何参数的话返回的是Object
类型数组。
String [] s= new String[]{
"dog", "lazy", "a", "over", "jumps", "fox", "brown", "quick", "A"
};
List<String> list = Arrays.asList(s);
Collections.reverse(list);
s=list.toArray(new String[0]);//没有指定类型的话会报错
25、不要在foreach循环中进行元素的remove/add操作。remove操作请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。(原因是java会将foreach循环翻译成Iterator迭代器)
//正确
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
Iterator<String> iterator = list.iterator();
while(itreator.hasNext()){
if(删除的条件){
iterator.remove();
}
}
//反例
for(String s:list){
if( ){
list.remove(s);
}
}
26、java 类中的main函数调用自身的方法需要通过类实例调用,直接调用只能够调用静态方法。
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!