1.关于数组
数组引用类型的变量的默认值为 null。当数组变量的实例后,如果没有没有显示的为每个元素赋值,Java 就会把该数组的所有元素初始化为其相应类型的默认值。(如int型的默认值为0,而对象类型数组默认值为null)。
2.如何通过反射创建对象
Class<?> clz = Class.forName("test.java.zxj.test_project.User");
Object object = clz.newInstance();
3.Java迭代器
例子
1、创建集合
ArrayList<String> al = new ArrayList<String>();
al.add("张三");
al.add("李四");
al.add("王二");
// 创建迭代器对象 注意这里创建迭代器不是用new 而是用集合的方法
Iterator<String> it = al.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
4.ConcurrentHashMap1.7与1.8的区别
Concurrenthashmap线程安全的,1.7是在jdk1.7中采用Segment + HashEntry的方式进行实现的,lock加在Segment上面。1.7size计算是先采用不加锁的方式,连续计算元素的个数,最多计算3次:1、如果前后两次计算结果相同,则说明计算出来的元素个数是准确的;2、如果前后两次计算结果都不同,则给每个Segment进行加锁,再计算一次元素的个数;
1.8中放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现,1.8中使用一个volatile类型的变量baseCount记录元素的个数,当插入新数据或则删除数据时,会通过addCount()方法更新baseCount,通过累加baseCount和CounterCell数组中的数量,即可得到元素的总个数;
5.避免死锁
使用多线程的时候,一种非常简单的避免死锁的方式就是:指定获取锁的顺序,并强制线程按照指定的顺序获取锁。因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了。
其他方法:1.破坏请求和保持条件,2.破坏不可抢占条件,3.破坏循坏等待条件。其中互斥不可能破坏。
6.可重入锁
可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。Java中ReentrantLock和synchronized都是可重入锁,可重入锁的一个优点是可一定程度避免死锁。
7.异常处理
在异常处理中,若try中的代码可能产生多种异常则可以对应多个catch语句,若catch中的参数类型有父类子类关系,此时应该将父类放在后面,子类放在前面。因为所有异常都是Exception的子类,如果你把Exception放在前边捕获,后边的catch将永远不会执行。
8.HashMap和Hashtable
HashMap无contains方法,ontains方法容易引起歧义,因此在HashMap中改成containsKey和containsValue方法来替换。
9.volatile和synchronized区别
1.关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且只能修改变量,而synchronized可以修饰方法,以及代码块。
2.多线程访问volatile不会发生阻塞,而synchronized会出现阻塞
3.volatile能保证数据的可见性,但不能保证原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存中的数据做同步
4.关键字volatile解决的下变量在多线程之间的可见性;而synchronized解决的是多线程之间资源同步问题
10.Arrays.asList()方法
Arrays.asList(),其将一个数组转化为一个List对象,这个方法会返回一个ArrayList类型的对象, 这个ArrayList类并非java.util.ArrayList类,而是Arrays类的内部类。
11.Math的ceil()方法和floor()方法
ceil:大于等于 x,并且与它最接近的整数。
floor:小于等于 x,且与 x 最接近的整数。
ceil 方法上有这么一段注释:If the argument value is less than zero but greater than -1.0, then the result is negative zero
如果参数小于0且大于-1.0,结果为 -0
12.关于AbstractSet和Set
AbstractSet类实现Set接口
HashSet继承 AbstractSet类,同时也实现set
13.jvm内存区
https://www.nowcoder.com/questionTerminal/51123ddacab84a158e121bc5fe3917eb
14.关于static静态变量
static变量也称作静态变量,静态变量和非静态变量的区别是:
静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。
而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
15.实现GBK编码字节流到UTF-8编码字节流的转换
byte[] src,dst;
dst=new String(src,"GBK").getBytes("UTF-8")
16.加载驱动的方法
- DriverManager.registerDriver(new com.mysql.jdbc.Driver());
2.System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver");
3.Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
17.会释放锁资源的方法
wait()和join(),join()底层就是调用wait()方法的,wait()释放锁资源,故join也释放锁资源。
18jvm堆,栈,方法区
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。
方法区和持久代的关系:
1、 java7之前,方法区位于永久代(PermGen),永久代和堆相互隔离,永久代的大小在启动JVM时可以设置一个固定值,不可变;
2、 java7中,static变量从永久代移到堆中;
3、 java8中,取消永久代,方法存放于元空间(Metaspace),元空间仍然与堆不相连,但与堆共享物理内存,逻辑上可认为在堆中
19.jvm内存溢出
简单的来说 java的堆内存分为两块:permantspace(持久带) 和 heap space。
持久带中主要存放用于存放静态类型数据,如 Java Class, Method 等, 与垃圾收集器要收集的Java对象关系不大。
而heapspace分为年轻带和年老带
年轻代的垃圾回收叫 Young GC, 年老代的垃圾回收叫 Full GC。
在年轻代中经历了N次(可配置)垃圾回收后仍然存活的对象,就会被复制到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象
年老代溢出原因有 循环上万次的字符串处理、创建上千万个对象、在一段代码内申请上百M甚至上G的内存,
持久代溢出原因: 动态加载了大量Java类而导致溢出
20.Math中的方法
Math.floor() 表示向下取整,返回double类型 (floor---地板)
Math.ceil() 表示向上取整,返回double类型 (ceil---天花板)
Math.round() 四舍五入,返回int类型