Java基础--重点难点
1、访问控制修饰符
修饰符 | 当前类 | 同一包内 | 子孙类(同一包) | 子孙类(不同包) | 其他包 |
---|---|---|---|---|---|
public | Y | Y | Y | Y | Y |
protected | Y | Y | Y | Y/N(说明) | N |
default(相当与不些) | Y | Y | Y | N | N |
private | Y | N | N | N | N |
说明:子类与基类不在同一包中:那么在子类中,子类实例可以访问其从基类继承而来的 protected 方法,而不能访问基类实例的protected方法。
2、数字的引用类型
Number的子类(基本数值类型的包装类)、大数值类:BigInteger、BigDecimal
3、Math类
基本数学运算(初等指数、对数、平方根、三角函数)
4、switch语句
支持 byte、short、int、char、String 类型
5、String、StringBuffer、StringBuild
StringBuffer --- 线程安全
StringBuild ---- 快、但线程不安全
6、日期时间类
-
Date ---> 日期时间类
-
SimpleDateFormat ---> 格式华日期,解析字符串为时间......
-
休眠(sleep)---> Thread.sleep(毫秒数)
-
测量时间 --->
-
long start=System.currentTimeMills(); // 返回当前时间,1970年01月01日至今的毫秒数
-
-
Calendar 类 ---> 日期时间类,它是抽象类,比 Date 类强大
-
GregorianCalendar 类 ---> 是 Calendar 类的一个具体实现类
7、正则表达式
- Pattern 类 ---> 自定义正则规则
- Matcher 类 ---> 根据 Pattern 对象(自定义的正则规则),对字符串解析 and 匹配
- PatternSyntaxException:正则中的异常处理类
8、输入类
Scanner 类: next()、hasNext()、nextLine()、hasNextLine()、......等方法
9、流、文件、IO操作:
Stream、File、IO操作等等
10、数组 & 集合框架
10-1 数组 + Arrays 数组工具类
- 数组元素可以是任意类型(即:基本类型、引用类型)。
- Arrays 工具类可以对数组进一些操作,如:排序等等
10-2 ArrayList
- 本质是对 数组Object[ ] 的封装,将该数组作为它的一个属性。元素存储在 数组中
- 对 ArrayList 的操作,实际上也是,用数组工具类---Arrays 来封装数组的CRUD以及排序等操作方法
- ArrayList 中的数组:默认容量为 10;扩容时,一般是增加当前容量的50% 。ArrayList 的容量属性,用户一般用不到,用的一般是 长度属性--size(元素的个数)
10-3 LinkedList
是双向链表。不是用数组来存储元素,是用内部类--Node来存储元素的
内部类---Node的关键属性:
item --> <E>
next --> <E>
prev --> <E>
LinkedList 的关键属性:
first ---> Node<E>
last ---> Node<E>
size ---> int
10-4 HashSet
继承了 HashMap,且实际是用 HashMap 的 key 来存放元素的。HashMap 的 key 是唯一性的,所以 HashSet 的元素可以达到唯一性。
主要属性:
map ---> HashMap
:用此属性来存放元素,此 map 的 value 全都为 PRSENT 属性变量PRESENT ---> new Object()
: 此属性为常量
对 HashSet 的操作 实际上是 封装对 map 的 Key 的操作。
10-5 LinkedHashSet
继承 HashSet,实现 Set 接口。它不是线程安全的
它自身的构造函数 实际上都是调用 父类的构造函数 ---> 即,HashSet 的 HashSet(int intialCapacity, float loadFactor, boolean dumy)
。实际上 HashSet 的这个构造方法是专门提供给 LinkedHashSet 使用的,本质是创建一个 LinkedHashMap
10-6 HashMap
常量属性:
- DEFAULT_INITIAL_CAPACITY=16 初识容量
- MAXIMUN_CAPACITY = 2^30 最大容量
- DEFAULT_LOAD_FACTOR = 0.75f 负载系数
- TREEIFY_THRESHOLD = 8 阀值
- UNTREEIFY_THRESHOLD = 6 取消阀值
- MIN_TREEIFY_THRESHOLD = 64 最小阀值
关键属性:
- size
- entrySet
- table
- loadFactor
- threshold
内部类:
- Node<K, V>
https://blog.csdn.net/qq_41345773/article/details/92066554
HashMap 的 key 的类型:
- 一切对象皆可为Key。如:Integer、Long、String、Object等。实际中,常使用 String 作为Key值
HashMap 的 key 是如何保证唯一性:
- 当两个 Key 的 Hash 值 相等时,HashMap会继续 比较这两个Key的值(即,
key1.equals(key2)
) - 作为 HashMap 的 Key 的 对象(类class),一般要重写两个方法: hashCode() 方法、equals() 方法。原因见下2句
- 1、hashCode() 方法:获取该对象的 Hash哈希值。不同的两个对象(值不同的对象),hash哈希值可能相同,所有还要使用 equals() 方法来比较。
- 2、String 已经重写了这两个方法,所以常使用 String 类型作为 Key。如果使用 自定义类型 作为 Key,则要重写这两个方法
HashMap 的 key 的底层存储:
- HashMap 使用的是数组+单向链表(红黑树)的形式进行存储key,数组的元素是链表(or 红黑树)。当链表中的元素就是 HashMap的Key。当链表的元素个数大于8个(一个阀值属性)时,链表将转换为红黑树来存储Key
- 哈希值Hash相同的Key(HashMap是对key取二次哈希)、hashMap 根据 key 的 二次hash 值 对 HashMap的默认承载量length(一般为16)取余 相同的 Key,存放在数组同一个位置。来决定该 key 放置在数组中的哪个索引。
- 数组中同一个位置的中的所有 Key,以 链表(or 红黑树) 的形式进行存储。
- 扩容:当元素过多,链表(or 红黑树)中的 Key 的数量也将增加,查找将变慢;这时就需要对数组进行扩容,HashMap 对该数组进行扩容后, 数组容量将是原来的 2倍。
HashMap 的 线程安全性问题:
- HashMap 是 线程不安全 的
- 可以 使用
Collections.synchronizeMap()
获取一个线程安全的集合 - ConcurrentHashMap、Hashtable 都是线程安全的。(因为 Hashtable 内含有 synchronize 关键字)
- HashMap 的 Key 可以为 Null,所有使用时 要考虑 Key的空指针问题,以及 整个集合 为Null 的问题。
最主要的实体类:Entry 类
Entry类实际上是一个单向的链表结构,在 HashMap 中的 Entry里面有的一些属性,如下
K key
:即,键值对的key。V value
:即,键值对的value。Entry<K, V> next
:将 一个Entry实体 视为链表的节点,该属性 就是 单向链表的节点指向下一个节点的指针int hash
:该元素的hash值。
在 HashMap 中 Entry类实际上是一个单向的链表结构 (将 Entry 视为节点);HashMap 采用 Entry数组 来存储key-value对,每一个键值对组成了一个Entry实体 。所以说 HashMap 是由 数组+单向链表(红黑树) 进行存储的
10-7 LinkedHashMap
参考:https://www.cnblogs.com/xiaoxi/p/6170590.html
继承了 HashMap,LinkedHashMap 是一个有序的 键值对 Map
如何达到有序:通过维护一个运行于所有条目的双向链表,LinkedHashMap保证了元素迭代的顺序。该迭代顺序可以是插入顺序或者是访问顺序。
最主要的实体类:Entry 类
K key
:即,键值对的key。V value
:即,键值对的value。Entry<K, V> next
:将 一个Entry实体 视为链表的节点,该属性 就是 单向链表的节点指向下一个节点的指针int hash
:该元素的hash值。Entry<K, V> before
:Entry<K, V> after
:
前4个属性是从 HashMap 继承,属性 before、after 是 LinkedHashMap 新增的。
属性 K key
、V value
用于存储集合中的元素(即,键值对),int hash
是决定该Entry实体在 Entry[] 数组中的哪个位置,next是用于维护HashMap指定table位置上连接的Entry的顺序的,before、After是用于维护Entry插入的先后顺序的。
属性 键值对(K key
+V value
) + Entry<K, V> next
+ int hash
组成 像 HashMap 那样的 数组+单向链表 的结构来存储 键值对元素。
属性 键值对(K key
+V value
) + Entry<K, V> before
+ Entry<K, V> after
组成双向循环链表,用于决定键值对元素的 插入顺序 or 访问顺序。
11、反射机制
1、发射是什么(反射式框架设计的灵魂)
-
JAVA反射机制是在运行状态中
- 对于任意一个类,都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能够调用它的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2、反射机制提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的成员变量和方法
- 生成动态代理
3、反射相关的主要 API:
- java.lang.Class:代表一个类(可暂时把它视为元类)
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造方法
4、反射的使用场景:
- Java编码时知道类和对象的具体信息,此时直接对类和对象进行操作即可,无需反射
- 如果编码时不知道类或者对象的具体信息,此时应该使用反射来实现
- 比如:类的名称、属性、属性值 等信息放在 XML 文件中,需要在运行时读取 XML 文件,动态获取 类的信息,在编译时根本无法知道该 对象or 类 可能属于哪些类,程序只依靠运行时信息来发现该 对象and类的真是信息。(Spring框架中,基于 XML 的控制反转、依赖注入等就是依靠 反射机制)
5、Class类:(也是Java 为什么可以做到这一点的原因)
- 对照镜子后可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class类型的对象。一个 Class对象包含了特定某个类的有关信息。
- Class 本身也是一个类
- Class 对象 只能由系统建立对象
- 一个类 在 JVM 中只会有一个Class 实例
- 一个Class 对象 对应的是一个加载到 JVM 中的一个
.class
文件。(也是Java 为什么可以做到这一点的原因) - 每个类的实例都会记得自己是由哪个 Class 实例所生成
- 通过 Class 可以完整地得到一个 类 中的 完整结构
参考:https://blog.csdn.net/weixin_42724467/article/details/84311385
6、获取反射入口(class 对象)的三种方法:
-
通过 Class.forName("全类名")
try { Class<?> perClazz = Class.forName("reflect_fanshe.Person"); System.out.println(perClazz); } catch (ClassNotFoundException e) { e.printStackTrace(); }
-
类名.class
Class<?> perClazz2 = Person.class;
-
对象.getClass()
Person person = new Person(); Class<?> perClazz3 = person.getClass();
7、根据反射入口对象(class) 获取类的各种信息:
在第 6 点中获取了 反射入口对象。根据反射入口对象(class) 获取类的各种信息。操作--略,参考链接
8、通过反射获取对象的实例,并操作对象
在 第 7 点 中可获取类的各种信息,便可建立该类的对象实例,然后再通过对象实例进行相关操作。操作--略,参考链接