每日一点Java基础小知识 — day5
欢迎来到叮当猫学编程的Java基础小知识系列~在这里,你将会看到叮当猫每日关于Java的基础知识总结,期待大家的点赞关注喔
-
System.out.println()
中:System是java.lang中的一个类,out是System内的一个成员变量,这个变量是一个java.io.PrintStream类的对象,println是其中的一个方法 -
线程安全的map在jdk:
-
HashMap,TreeMap 未进行同步考虑,是线程不安全的
-
HashTable 和 ConcurrentHashMap 都是线程安全的。区别在于他们对加锁的范围不同,HashTable 对整张Hash表进行加锁,而ConcurrentHashMap将Hash表分为16桶(segment),每次只对需要的桶进行加锁
-
Collections 类提供了synchronizedXxx()方法,可以将指定的集合包装成线程同步的集合。比如:
List list = Collections.synchronizedList(new ArrayList());
Set set = Collections.synchronizedSet(new HashSet());
-
-
关于接口与抽象类:
-
抽象类特点:
- 抽象类中可以构造方法
- 抽象类中可以存在普通属性,方法,静态属性和方法
- 抽象类中可以存在抽象方法
- 如果一个类中有一个抽象方法,那么当前类一定是抽象类;抽象类中不一定有抽象方法
- 抽象类中的抽象方法,需要有子类实现,如果子类不实现,则子类也需要定义为抽象的。
-
接口
- 在接口中只有方法的声明,没有方法体。
- 在接口中只有常量,因为定义的变量,在编译的时候都会默认加上public static final
- 在接口中的方法,永远都被public来修饰
- 接口中没有构造方法,也不能实例化接口的对象
- 接口可以实现多继承
- 接口中定义的方法都需要有实现类来实现,如果实现类不能实现接口中的所有方法,则实现类定义为抽象类
-
-
关于
java concurrent
包下的四个类:- Semaphore:类,控制某个资源可被同时访问的个数
- ReentrantLock:类,具有与使用synchronized方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大
- Future:接口,表示异步计算的结果
- CountDownLatch: 类,可以用来在一个线程中等待多个线程完成任务的类。
-
hashCode方法本质就是一个哈希函数,这是Object类的作者说明的。Object类的作者在注释的最后一段的括号中写道:将对象的地址值映射为integer类型的哈希值。但hashCode()并不完全可靠的,有时候不同的对象他们生成的hashcode也会一样,因此hashCode()只能说是大部分时候可靠。因此我们也需要重写equals()方法,但因为重写的equals()比较全面比较复杂,会造成程序效率低下,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高。因此,正常的操作流程是先用hashCode()去对比两个对象,如果hashCode()不一样,则表示这两个对象肯定不相等,直接返回false,如果hashCode()相同,再对比他们的equals()
综上所述:
equals()相等的两个对象hashCode()一定相等
hashCode()相等的两个对象equal()不一定相等
-
创建socket连接:
- 服务器端:ServerSocket提供的实例
ServerSocket server = new ServerSocket(端口号)
- 客户端:Socket提供的实例
Socket client = new Socket(IP地址,端口号)
- 服务器端:ServerSocket提供的实例
-
关于访问权限:
-
对于外部类而言,它也可以使用访问控制符修饰,但外部类只能有两种访问控制级别: public 和默认
因为外部类没有处于任何类的内部,也就没有其所在类的内部、所在类的子类两个范围,因此 private 和 protected 访问控制符对外部类没有意义
-
内部类的上一级程序单元是外部类,它具有 4 个作用域:同一个类(private)、同一个包(protected)和任何位置(public)
-
因为局部成员的作用域是所在方法,其他程序单元永远不可能访问另一个方法中的局部变量,所以所有的局部成员都不能使用访问控制修饰符修饰
-
-
Spring的API设计很不错,基本上根据英文翻译就能知道作用:
Required
:必须的。说明必须要有事物,没有就新建事物supports
:支持。说明仅仅是支持事务,没有事务就非事务方式执行mandatory
:强制的。说明一定要有事务,没有事务就抛出异常required_new
:必须新建事物。如果当前存在事物就挂起not_supported
:不支持事物,如果存在事物就挂起never
:绝不有事务。如果存在事物就抛出异常
-
关于Collection:
-
jvm classLoader architecture(Java类加载器)
-
Bootstrap ClassLoader/启动类加载器
主要负责jdk_home/lib目录下的核心 api 或 -Xbootclasspath 选项指定的jar包装入工作
-
Extension ClassLoader/扩展类加载器
主要负责jdk_home/lib/ext目录下的jar包或 -Djava.ext.dirs 指定目录下的jar包装入工作
-
System ClassLoader/系统类加载器
主要负责java -classpath/-Djava.class.path所指的目录下的类与jar包装入工作
-
User Custom ClassLoader/用户自定义类加载器(java.lang.ClassLoader的子类)
在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性.
-
-
关于数组的定义:
- 定义一维数组时,必须显式指明数组的长度
- 定义***数组时,其一维数组的长度必须首先指明,其他维数组长度可以稍后指定
- 采用给定值初始化数组时,不必指明长度
- “[]” 是数组运算符的意思,在声明一个数组时,数组运算符可以放在数据类型与变量之间,也可以放在变量之后
-
对于N维数组(N≥2),初始化时不一定要将所有数组都初始化,可以先只为外层数组分配数组空间。等待需要时,再为其它维数组分配空间。第一个数组(最外层数组)的空间是必须分配的,也不能先分配第二个以后的数组再分配第一个数组
比如定一个二维数组,第一维的长度是3,第二维长度暂时不确定,可以在以后的代码中定义:
int[][] arr = int[5][]; arr[0] = new int[2]; arr[1] = new int[1]; arr[2] = new int[5];
-
java是自动管理内存的,通常情况下程序运行到稳定状态,内存大小也达到一个基本稳定的值。但是内存泄露导致Gc不能回收泄露的垃圾,内存不断变大,最终超出内存界限,抛出
OutOfMemoryExpection
-
关于try-catch-finally:
- 不管有木有出现异常,finally块中代码都会执行
- 当try和catch中有return时,finally仍然会执行
- finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的
- finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值