一、常用类
1) String相关类
1.String
1.1 初识字符串
声明字符串
1 2 3 4 5 String s = new String("uden" ); String s = new String(); s = sc.next();
转换为二进制的方法
1 2 result = Integer.toBinaryString(num)
1.2字符串的一系列操作
连接字符串
1 2 3 4 5 6 7 8 public class join {public static void main (String[] args) { String s1 = new String("Hello" ); String s1 = new String("Java" ); String s = s1+" " +s2; System.out.println(s); } }
获取字符串长度
1 int size = str.length();
字符串查找
1 2 3 4 5 6 7 int index = str.indexOf(substr);int index = str.indexOf("a" );int index = str.lastindexOf(substr);int index = str.lastindexOf("a" );
获取指定位置的字符
1 char mychar = str.charAt(int index);
获取子字符串
1 2 3 String substr = str.substring(int beginIndex); String substr = str.substring(int beginIndex,int endIndex);
去除空格
字符串替换
1 2 str.replace(char oldChar,char newChar); str.replaceAll(String regex,String newstr);
比较字符串
比较字符串不能用 “==” 因为字符串是对象,即使是内容相同,内存地址也是不同的,也会是false;
这里应该使用equals方法;
1 2 3 str.equals(String otherString); str.equalsIgnoreCase(String otherString);
按字典顺序比较两个字符串
1 str.compareTo(String otherstr);
大小写转换
1 2 3 4 5 6 7 public static void main (String[] args) { String str = new String("abc DEF" ); String newstr1 = str.toUpperCase(); String newstr2 = str.toLowerCase(); System.out,println(newstr1); System.out,println(newstr1); }
字符串分割
1 2 3 String[] firstArray = str.split("\\." ,2 );
字符串反转
1 2 StringBuilder stringBuilder = new StringBuilder(s); System.out.print(stringBuilder.reverse().toString());
1.3 关于正则表达式(初级)
注意: 在正则表达式中“.”代表任何一个字符,因此在正则表达式如果想使用普通意义的"." ,需要写成"\.";
2. StringBuffer
2.1初始化
StringBuffer() 构造一个其中不带字符的字符串缓冲区,其初始容量为 16 个字符。
1 StringBuffer sb = new StringBuffer("william" );
2.2 关于StringBuffer的一些方法
添加字符
1 2 3 4 5 6 7 8 StringBuffer sb = new StringBuffer("william" ); sb.append("wiam" ); System.out.println(sb); sb.insert(0 ,"w" ); System.out.println(sb);
删除字符
1 2 3 4 5 6 7 sb.deleteCharAt(1 ); System.out.println(sb); sb.delete(1 ,3 ); System.out.println(sb);
替换指定位置的字符串
1 2 3 4 sb.replace(0 ,1 ,"chengningzuishuai" ); System.out.println(sb);
反转字符串
1 2 3 sb.reverse(); System.out.println(sb);
参考:https://blog.csdn.net/weixin_44519467/article/details/103947361?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163092725916780265450059%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163092725916780265450059&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-2-103947361.first_rank_v2_pc_rank_v29&utm_term=stringbuffer&spm=1018.2226.3001.4187
3. StringBuilder
3.1 初始化
1 StringBuilder sb = new StringBuilder("Hello mercury" );
3.2 几个常用的方法
和StringBuffer的都一样
添加字符串
1 2 3 4 5 6 7 sb.append("chenningzuishuai" ); System.out.println(sb); sb.insert(2 ,"william" ); System.out.println(sb);
删除字符串
1 2 3 4 5 6 7 sb.deleteCharAt(1 ); System.out.println(sb); sb.delete(1 ,30 ); System.out.println(sb);
替换指定位置的字符串
1 2 3 4 sb.replace(0 ,1 ,"chengningzuishuai" ); System.out.println(sb);```
反转字符串
1 2 3 sb.reverse(); System.out.println(sb);
4. 关于这几个字符串的区别
String
StringBuffer
StringBuilder
String的值是不可变的(里面是final),这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间
StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量
可变类,速度更快
不可变
可变
可变
线程安全
线程不安全
多线程操作字符串
单线程操作字符串
(1)如果要操作少量的数据用 String;
(2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;
(3)单线程操作字符串缓冲区下操作大量数据 StringBuilder。
在不考虑线程安全的情况下,现阶段应使用StringBuilder而不是StringBuffer
参考:https://blog.csdn.net/itchuxuezhe_yang/article/details/89966303?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163092981516780366546179%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163092981516780366546179&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-89966303.first_rank_v2_pc_rank_v29&utm_term=stringbuilder&spm=1018.2226.3001.4187
2) Math类
定义了一些常量,如 Math.PI Math.E
1.常用的数学方法
三角函数方法
1 2 3 4 5 6 7 public class mathdemo { public static void main (String[] args) { System.out.println("90度的正弦值:" +Math.sin(Math.PI/2 )); System.out.println("0度的余弦值:" +Math.cos(0 )); System.out.println("60度的正弦值:" +Math.tan(Math.PI/3 )); } }
指数函数方法
1 2 3 4 5 6 7 8 9 10 11 public class ExponentFunction { public static void main (String[] args) { System.out.println("e的平方值" + Math.exp(2 )); System.out.println("以e为底2的对数值" + Math.log(2 )); System.out.println("以10为底2的对数值" + Math.log10(2 )); System.out.println("4的平方根值" + Math.sqrt(4 )); System.out.println("8的立方根值" + Math.cbrt(8 )); System.out.println("2的2次方值" + Math.pow(2 ,2 )); } }
取整函数
1 2 3 4 public static double ceil ( double a) ;public static double floor ( double a) ;public static double rint ( double a) ;
取最大值,最小值,绝对值函数方法
1 2 3 4 5 public static void main (String[] args) { System.out.println("4和8较大者" +Math.max(4 ,8 )); System.out.println("4.4和4较小者" +Math.min(4.4 ,4 )); System.out.println("-7的绝对值" +Math.abs(-7 )); }
3) Random类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class randomdemo { public static void main (String[] args) { Random r = new Random(); System.out.println("随机产生一个整数" +r.nextInt()); System.out.println("随机产生一个大于等于0且小于10的整数" +r.nextInt(10 )); System.out.println("随机产生布尔型的值" +r.nextBoolean()); System.out.println("随机产生一个双精度型的的值" +r.nextDouble()); System.out.println("随机产生一个浮点型的的值" +r.nextFloat()); } }
4) 大数字计算类
1. BigInteger
1 2 3 4 5 6 7 8 9 10 11 12 13 public class BigIntegerdemo { public static void main (String[] args) { BigInteger big = new BigInteger("4" ); System.out.println("加法操作" + big.add(new BigInteger("2" ))); System.out.println("减法操作" + big.subtract(new BigInteger("2" ))); System.out.println("乘法操作" + big.multiply(new BigInteger("2" ))); System.out.println("除法操作" + big.divide(new BigInteger("2" ))); System.out.println("乘方操作" + big.pow(2 )); System.out.println("取相反数操作" + big.negate()); } }
2. BigDecimal
与BigInteger不同的是,BigDecimal可以进行小数的计算,包括float和double,值得注意的是,这个的加法减法等方法需要自己去定义
1 2 3 public BigDecimal (double val) ;public BigDecimal (String val) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class BigDecimalDemo { public static void main (String[] args) { BigDecimalDemo big = new BigDecimalDemo(); System.out.println("两数相加的结果" +big.add(7.5 ,8.9 )); } public BigDecimal add (double value1, double value2) { BigDecimal b1 = new BigDecimal(Double.toString(value1)); BigDecimal b2 = new BigDecimal(Double.toString(value2)); return b1.add(b2); } }
二、集合
集合的索引也是从0开始
1)Collection接口
Collection是根接口,一般不直接使用,后面的list接口和Set接口都继承了Collection接口,因此是通用的;而遍历集合一般都是通过迭代器实现;这里给出一个实例
1 2 3 4 5 6 7 8 9 10 11 12 import java.util*public class Muster { public static void main () { Collection<String> list = new ArrayList<>(); list.add("a" ); Iterator<String> it = list.iterator(); while (it.hasNext()){ String str = it.next(); System.out.println(str); } } }
除此之外,collection中主要有以下方法
方法
功能描述
add(E e)
添加指定对象
remove(Object o)
将指定对象移除
isEmpty
判断是否为空
itertor()
迭代器
size()
获取元素个数
2)List集合
List中主要包含了两种实现类,即ArrayList和LinkedList,他们的主要区别就是,List中类似数组存储,而LinkedList则是使用链表存储。
1 2 3 List<E> list = new ArrayList<>(); List<E> list2 = new LinkedList<>();
List集合继承了collection接口,有他的所有方法,并且多了两个方法:
方法
作用
get(int index)
获取指定那个位置的集合元素
set(int index,Object obj)
顾名思义就是设置元素的
来个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class ArrayListdemo { public static void main (String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("a" ); list.add("b" ); list.add("c" ); list.remove(2 ); for (int i = 0 ; i < list.size(); i++) { System.out.println(list.get(i)); } } }
3)Set集合
Set继承了Collection接口;Set集合对象不按特定的顺序排序,只是简单的加入数据,但是Set集合中不能包含重复的对象,常用的实现类有HashSet类和TreeSet类
1. HashSet实现类
数据结构:JDK1.8之前:哈希表(数组+单向链表);JDK1.8之后:哈希表(数组+单向链表+红黑树),当链表长度超过阈值(8)时,链表将转换为红黑树。
特点:查询快,元素无序,元素不可重复,没有索引;
底层分析:哈希表底层用数组+单向链表实现,即使用链表处理冲突,同一Hash值的元素都存储在一个链表里,但是当位于一个链表中的元素较多,即Hash值相等的元素较多,通过key值依次查找的效率降低。JDK1.8之后,哈希表底层采用数据+单向链表+红黑树实现,当链表长度超过阈值(8)时,链表将转换为红黑树,极大缩短查询时间。
2. TreeSet实现类
数据结构:红黑树
特点:查询快,元素有序,元素不可重复,没有索引;
底层分析:TreeSet实现了继承于Set接口的SortedSet接口 ,它支持两种排序方法,自然排序和定制排序,自然排序的意思就是放入元素“a”,“b”,a会自然地排在b前面,其中还有几个特有方法。
first() 返回第一个元素; last() 返回最后一个元素;comparator() 返回排序比较器;
引用自https://blog.csdn.net/weixin_42559574/article/details/108203595?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163110337616780255269862%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163110337616780255269862&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-108203595.first_rank_v2_pc_rank_v29&utm_term=Java集合类&spm=1018.2226.3001.4187
3)Map集合
Map没有继承collection类,它提供的是key到value的映射,Map中不能包含相同的key,每个key只能映射一个value;其实key就相当于下标。
1. Map接口
其包含的主要方法
方法
功能
put(K key,V value)
添加指定的key到value的映射关系
containKey(Object key)
如果包含指定key的映射关系,则返回true
containsValue(Object value)
如果包含指定key的映射关系,则返回true
get(Object key)
如果存在指定的key对象,则返回对应的value值,否则返回null
keySet()
返回所有的key的值形成的Set集合
values()
返回所有的value的值形成的Collection集合
2. Map接口实现的类
主要有HashMap和TreeMap,建议使用HashMap,因为效率更高,而TreeMap有一定的顺序,若希望Map集合里的对象也有一定的顺序,则使用TreeMap实现Map集合
1 2 3 4 Map<String,String> map = new HashMap<>(); Map<String,String> map = new TreeMap<>();
三、 枚举类型
1)枚举类的使用
枚举类的理解:类的对象只有有限个,确定的,就为枚举类
当需要定义一组常量时,强烈建议使用枚举类
如果枚举类中只有一个对象,则可以作为单例模式的实现方式
2)使用enum类型来定义常量
1 2 3 4 5 public enum con { con_A, con_B, con_C }
3)枚举类的常用方法
方法名称
作用
使用方法
values()
将枚举类型的成员以数组的形式返回(也可以通过该方法获取枚举类类型的成员)
枚举类型名称.values()
valuesOf()
将普通字符串转换为枚举实例
枚举类型名称.valueOf(“abc”)
compareTo()
比较两个枚举对象在定义时的顺序(正值表示在参数在调用该方法的枚举对象之前,负值则是之后)
枚举对象.compareTo()
ordinal
得到枚举成员的位置索引
枚举对象.ordinal()
构造函数 在写枚举类构造方法的时候权限修饰符应该为private;
四、泛型
1)初识泛型
把元素的类型设计成一个参数,这个参数就是泛型
如果集合不使用泛型
就会出现种种问题
使用泛型
问题迎刃而解
然后输出(这里复习一下增强for循环和迭代器)
问题迎刃而解
然后输出(这里复习一下增强for循环和迭代器)
注意点 :集合中<>中填泛型时不能时基本数据类型(比如int),必须是一个类,例如是int需要填包装类Integer
2)自定义泛型
1、泛型类
这里的T相当于一个参数,就当成其他的数据类型一样用
1 2 3 4 5 6 7 8 9 10 11 12 13 public class test { @Test public void test1 () { Order order = new Order(); order.setOrderT(123 ); order.setOrderT("ABC" ); Order<String> order1 = new Order<String>("orderAA" ) } }
3)泛型方法
泛型方法里的泛型参数和泛型类里的泛型参数是没有关系的
上图中因为返回的时List类型的所以还有个List,特别注意标明是泛型方法要有个 < E >
测试泛型方法
泛型方法是可以声明为静态的.原因就是:泛型参数实在调用方法时确定的,并非是在实例化类时确定的
4)通配符的使用
通配符 : ?
1 2 3 4 5 6 7 public void print (List<?> list) { Iterator<?> iterator = list.iterator(); while (iterator.hasNext()){ Object obj = iterator.next; System.out.println(obj); } }
有限制条件的通配符的使用
? extends Person 向下限制,只接受Person类以下的类型
? super Person 向下限制,只接受Person类以上的类型
1 2 3 4 5 public void doSomething (A<? extends List> a) { } List<? extends list> list = null ;
比如在这里 list1 = list5 就会报错
五、注解
1)初识注解
2)元注解
元注解主要是在定义自定义的注解的时候用
3)自定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Test03 { @MyAnnotation2(age = 18,name = "陈帅") ; public void test () {} @Target({Element.TYPE,Elementtype.NETHOD}) @Retention(RetenionPolicy.RUNTIME) @interface MyAnnotation2{ String name () default "" ; int age () ; int id () default -1 ; String[] schools default ("西柚牛逼" ,"Mercury最帅" ) ; } @Target({Element.TYPE,Elementtype.NETHOD}) @Retention(RetenionPolicy.RUNTIME) @interface MyAnnotation3{ String value () ; } }
如果有default即有默认值,可以不用赋值
六、反射
1)关于静态语言和动态语言
2)初识反射
例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Test02 { public static void main (String[] args) throws ClassNotFoundException { Class c1 = class.forName("com.kuang.reflection.User" ); System.out.println(c1); Class c2 = class.forName("com.kuang.reflection.User" ); Class c3 = class.forName("com.kuang.reflection.User" ); Class c4 = class.forName("com.kuang.reflection.User" ); System.out.println(c2.hashcode()); System.out.println(c3.hashcode()); System.out.println(c4.hashcode()); } }class User {...}
3)获取class的实例
实操获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Test { public static void main (String[] args) throws ClassNotFoundExcepion { Person person = new Student(); System.out.println("这个人是" + person.name); Class c1 = person.getClass(); System.out.println(c1.hashcode()); Class c2 = Class.forname("com.reflection.Student" ) System.out.println(c2.hashcode()); Class c3 = Student.class; System.out.println(c3.hashcode()); } }class Person {...}class student extends Person {...}
4)关于类加载器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class Test { public static void main (String[] args) throws ClassNotFoundException { class c1 = Class.forname("com.kuang.reflection.User" ); User user = new user(); c1 = user.getclass(); System.out.println(c1.getName); System.out.println(c1.getSimpleName()); Field[] fields = c1.getFields(); fields = c1.getDeclaredFields(); for (Field field : fields){ System.out.println(field); } Method[] methods = c1.getMethods(); for (Method method : methods){ System.out.println("正常的" +method); } methods = c1.getDeclaredMethods(); for (Method method : method){ System,out.println("getDeclaredMethods" +method); } Method getName = c1.getMethod("getName" ,null ); Method setName = c1.getMethod("setName" ,String.class); System.out.println(getName); System.out.println(setName); } Constructor[] constructors = c1.getConstructors(); for (Constructor constructor : constructors){ System.out.println(constructors); } } Constructor declaredConstructor = c1.getDeclaredConstructor(String.class,int .class,int .class); System.out.println(declaredConstructor);
5)通过反射创建对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class Test {public static void main (String[] args) throws ClassNotFoundException,IllegalAccessException { Class c1 = Class.forname("com.reflection,User" ); User user = (user)c1.newInstance(); System.out.println(user); Constructor declaredConstructor = c1.getDeclaredConstructor(String.class,int .class,int .class); User user2 = (user)constructor.newInstance("陈帅" ,001 ,18 ); System.out.println(user2); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 User user3 = (User)c1.newInstance(); Method setName = c1.getDeclaredMethod("setName" ,String.class); setName.invoke(user3,"陈帅" ); System.out.println(user3.getName()); User user4 = (User)c1.newInstance(); Field name = c1.getDeclaredField("name" ); name.setAccessible(true ); name.set(user4,"陈帅牛逼" ); System.out.println(user4.getName());
实操
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class xingneng { public static void test () { user user = new user(); long starTime = System.currentTimeMillis(); for (int i = 0 ; i < 1000000000 ; i++) { user.getName(); } long endtime = System.currentTimeMillis(); System.out.println("普通方法执行10次" +(endtime-starTime)+ "ms" ); } public static void test2 () throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { user user = new user(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName" , null ); long starTime = System.currentTimeMillis(); for (int i = 0 ; i < 1000000000 ; i++) { getName.invoke(user,null ); } long endtime = System.currentTimeMillis(); System.out.println("反射方法执行10次" +(endtime-starTime)+ "ms" ); } public static void test3 () throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { user user = new user(); Class c1 = user.getClass(); Method getName = c1.getDeclaredMethod("getName" , null ); getName.setAccessible(true ); long starTime = System.currentTimeMillis(); for (int i = 0 ; i < 1000000000 ; i++) { getName.invoke(user,null ); } long endtime = System.currentTimeMillis(); System.out.println("反射方法执行10次" +(endtime-starTime)+ "ms" ); } public static void main (String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException { test(); test2(); test3(); } }
程序运行结果
所以关闭检测可以提升程序的效率
6)反射操作泛型
7)反射操作注解
getAnnotations
getAnnotation
七、多线程
1、实现多线程
多线程在我目前开发中用的不算多,这里知识简单的梳理一下多线程的知识点。
实现 多线程的方法在Java中有两种,一种是继承thread类,还有一种方法就是重写runable方法
1)、继承thread类
这种方法就是写一个类来继承thread类,在这个类中还需要写一个run方法来运行这个线程,然后在主类中就可以创建这个线程然后启动该线程。以代码为例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Thread1 extends Thread { private String name; public Thread1 (String name) { this .name=name; } public void run () { for (int i = 0 ; i < 5 ; i++) { System.out.println(name + "运行 : " + i); try { sleep((int ) Math.random() * 10 ); } catch (InterruptedException e) { e.printStackTrace(); } } } }public class Main { public static void main (String[] args) { Thread1 mTh1=new Thread1("A" ); Thread1 mTh2=new Thread1("B" ); mTh1.start(); mTh2.start(); } }
在线程运行的时候,需要注意下:两个线程启动时,在处理机上是并发运行的,因此线程输出的顺序并不确定。(所以在做PTA上面的题可能多提交几遍说不定就可以了。)
2) 重写Runable接口
具体需要子类实现Runable接口,然后重写里面的run方法就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Thread2 implements Runnable { private String name; public Thread2 (String name) { this .name=name; } @Override public void run () { for (int i = 0 ; i < 5 ; i++) { System.out.println(name + "运行 : " + i); try { Thread.sleep((int ) Math.random() * 10 ); } catch (InterruptedException e) { e.printStackTrace(); } } } }public class Main { public static void main (String[] args) { new Thread(new Thread2("C" )).start(); new Thread(new Thread2("D" )).start(); } }
线程有好几种状态,如: 阻塞状态,准备状态等等,这一部分的内容以及关于线程的调度问题具体请参照操作系统部分
2、多线程常用的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 start() 函数 sleep()函数 join()函数 yield()函数 setPriority()函数 interrupt()函数 向线程发出一个中断信号,让线程在无限等待的时候能够抛出,从而结束线程(并不是中断哪个线程) wait()函数
3、线程同步
1)、synchronized关键字
是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。
除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/区块 /},它的作用域是当前对象;
synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;
总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
异常
自动装箱机制
深拷贝 浅拷贝 引用拷贝
I/O