共计 23404 个字符,预计需要花费 59 分钟才能阅读完成。
概述
所有能够调用的都是 API
目标
学习 java 里提供的各种工具类的应用(工具类提供的构造方法,一般办法,成员变量)
学习工具
api 手册
Object
概述
类 Object 是类层次结构的根类。每个类都应用 Object 作为超类。所有对象(包含数组)都实现这个类的办法。
罕用办法
System.out.println(o.hashCode() );// 返回该对象的哈希码值。– 哈希码值了解为编号
System.out.println(o.toString() );// 返回该对象的字符串示意
System.out.println(o);// 对象在内存中的地址值
System.out.println(o.equals(123) );// 批示其余某个对象是否与此对象“相等”。
总结
–toString– 默认应用的是 Object 的 toString()展现的是地址值,如果想要属性值就要进行重写
– 重写 equals– 默认应用的是 Object 的 equals()展现的是地址值之间的比拟,不想比拟地址值,想比拟属性值
– 主动生成 –generate….
instanceof java 里的关键字,通常用来判断 obj instanceof student obj 是不是学生类型。
string
概述
String 类代表字符串。Java 程序中的所有字符串字面值(如 “abc”)都作为此类的实例实现。
字符串是常量;它们的值在创立之后不能更改。字符串缓冲区反对可变的字符串。
罕用办法
char charAt(int index)
• 返回指定索引处的 char 值。
• String concat(String str)
• 将指定字符串连贯到此字符串的结尾。
• boolean contains(CharSequence s)
• 当且仅当此字符串蕴含指定的 char 值序列时,返回 true。
• boolean endsWith(String suffix)
• 测试此字符串是否以指定的后缀完结。
• boolean equals(Object anObject)
• 将此字符串与指定的对象比拟。
• byte[] getBytes()
• int hashCode()
• 返回此字符串的哈希码。
• int indexOf(String str)
• 返回指定子字符串在此字符串中第一次呈现处的索引。
boolean isEmpty()
• 当且仅当 length() 为 0 时返回 true。
• int length()
• 返回此字符串的长度。
• int lastIndexOf(String str)
• 返回指定子字符串在此字符串中最左边呈现处的索引。
String replace(char oldChar, char newChar)
用新的代替旧的
• String[] split(String regex)
• 依据给定正则表达式的匹配拆分此字符串。
• boolean startsWith(String prefix)
• 测试此字符串是否以指定的前缀开始。
• String substring(int beginIndex)
• 返回一个新的字符串,它是此字符串的一个子字符串。
• String substring(int beginIndex, int endIndex)
• 返回一个新字符串,它是此字符串的一个子字符串。
• char[] toCharArray()
• 将此字符串转换为一个新的字符数组。
• String toLowerCase() 全副转换为小写
• String toUpperCase() 全副转换为大写
String trim()
• 返回字符串的正本,疏忽前导空白和尾部空白。
• static String valueOf(int i)
• 返回 int 参数的字符串示意模式。
StringBuilder/StringBuffer
概述
都是用来进行字符串拼接的优化计划
罕用办法
StringBuilder append(string b)
包装类
概述
为了对应的根本类型提供丰盛的办法
根本类型 byte short int long float double char boolean
包装类型 Byte Short Integer Long Float Double Character Boolean
Number
– 提供将示意的数值转换为 byte、double、float、int、long 和 short 的办法。
integer
创建对象
Integer(int value)
罕用办法
int intValue()
• 以 int 类型返回该 Integer 的值。
• static int parseInt(String s)
• 将字符串参数作为有符号的十进制整数进行解析。
• static Integer valueOf(int i)
• 返回一个示意指定的 int 值的 Integer 实例。
日期类
概述
类 Date 示意特定的霎时,准确到毫秒
创建对象
Date()
罕用办法
getXxx()
System.out.println(d.getTime() );// 从 1970,1,1 零点到当初的毫秒值
System.out.println(d.getClass() );// 返回此 Object 的运行时类 System.out.println(d.getDate() );// 获取明天是一个月里的第几天
System.out.println(d.getHours() );// 获取当初是几点
System.out.println(d.getDay() );// 明天星期几
System.out.println(d.getMinutes() );// 获取一个小时里的第几分钟
System.out.println(d.getMonth() + 1 );// 底层获取到天然月 -1,0~11 示意 12 个月
System.out.println(d.getSeconds() );// 获取当初是哪一秒
System.out.println(d.getYear() );// 获取从 1900 年到当初一共是多少年
System.out.println(d.toLocaleString());//2020-9-15 14:40:03
日期工具 SimpleDateFormat
概述
把 String 类型的日期 和 Date 类型的日期 互转
创建对象
SimpleDateFormat(String pattern)
罕用办法
Date -> String : String format(Date date)
String -> Date : Date parse(String text)
BigDecimal/BigInteger
概述
BigDecimal 专门用来解决 小数运算 不准确的问题
BigInteger 专门用来解决 超大的 整数运算
不可变的、任意精度的有符号十进制数。
BigDecimal 创建对象
BigDecimal(double val) – 构造方法有坑,会使计算更加不准确。
BigDecimal(String val)
罕用办法
加法运算: BigDecimal add(BigDecimal augend)
减法运算: BigDecimal subtract(BigDecimal subtrahend)
乘法运算: BigDecimal multiply(BigDecimal multiplicand)
除法运算: BigDecimal divide(BigDecimal divisor,要保留的小数位,舍入模式)四舍五入 BigDecimal.ROUND_HALF_UP
File 文件工具类
概述
文件和目录路径名的形象示意模式
创建对象
File(String pathname)
调用办法
System.out.println(file.length() );// 获取文件的大小
System.out.println(file.exists() );// 判断文件是否与存在
System.out.println(file.isFile() );// 判断资源是文件吗
System.out.println(file.isDirectory() );// 判断资源是文件夹吗
System.out.println(file.getName() );// 获取文件名
System.out.println(file.getAbsolutePath() );// 获取残缺门路
System.out.println(file.getParent() );// 获取文件的父门路
file = new File(“F:java2.txt”);
System.out.println(file.createNewFile() );// 创立不存在的文件 2.txt
file = new File(“F:javaabc”);
System.out.println(file.mkdir() );// 创立不存在的文件夹 abc
file = new File(“F:javamnx”);
System.out.println(file.mkdirs() );// 创立不存在的多个文件夹 m n x
file = new File(“F:java2.txt”);
System.out.println(file.delete() );// 删除文件 或者 空的文件夹
file = new File(“F:java”);
String[] names = file.list() ;// 获取所有资源的 名字 存入 String[]
System.out.println(Arrays.toString(names) );//[1.txt, abc, m]
File[] fs = file.listFiles() ;// 获取所有资源 并封装成一个一个的 File 对象, 存入 File[]– 举荐!!
System.out.println(Arrays.toString(fs) );
//TODO 创立 3 个 File 对象并存入容器里(数组)
File f1 = new File(“ 文件或者文件夹门路 1”);
File f2 = new File(“ 文件或者文件夹门路 2”);
File f3 = new File(“ 文件或者文件夹门路 3”);
File[] a = new File[3];// 怎么决定数组的类型?– 看你要存的数据的 类型
• a[0] = f1;
• a[1] = f2;
• a[2] = f3;
• System.out.println(Arrays.toString(a) );
统计文件夹里 所有文件的大小
1, 接管用户输出 文件夹门路
String path = new Scanner(System.in).nextLine();
File ff = new File(path);// 封装成 File 对象
2, 列出 文件夹里 的所有资源, 并封装成一个一个的 File 对象, 放入 File[]
• File[] aa = ff.listFiles() ;
• long sum = 0 ;// 定义变量, 记录文件的总和
• // 循环数组, 获取每个资源 aa[i]
• for (int i = 0; i < aa.length ; i++) {
• // 3, 判断资源 是文件夹 还是文件
• if(aa[i].isDirectory()){// 如果是文件夹返回 true
• System.out.println(aa[i].getName());//4, 如果是文件夹, 输入文件夹名称
• }
else if(aa[i].isFile()){
• // 5. 如果是文件 求和.
• sum = sum + aa[i].length() ;
• }
• }
• System.out.println(“ 文件的总大小是:”+sum);
• }
• }
能够应用父类的办法, 也能够应用本人的扩大办法. 而且还能 new
概述
字节流通罕用来对数据 进行 读写操作.
能够对电脑里的 二进制文件 进行操作.
字节流读 : 是指 从磁盘到 程序 的过程, 是指程序须要读取数据
InputStream
是父类, 而且被润饰成一个抽象类. 不能 new, 咱们只学习父类的共性办法
罕用办法
abstract int read()
从输出流中读取数据的下一个字节。
int read(byte[] b)
从输出流中读取肯定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len)
将输出流中最多 len 个数据字节读入 byte 数组。
void close()
敞开此输出流并开释与该流关联的所有系统资源。
FileInputStream
能够应用父类的办法, 也能够应用本人的扩大办法. 而且还能 new
FileInputStream 从文件系统中的某个文件中取得输出字节。
创建对象
FileInputStream(String name)
FileInputStream(File file)
BufferedInputStream 缓冲流 / 高级流
能够应用父类的办法, 也能够应用本人的扩大办法. 而且还能 new
在创立 BufferedInputStream 时,会创立一个外部缓冲区数组。
字节流写出
是指从程序到磁盘的过程
OutputStream
此抽象类是示意输入字节流的所有类的超类。
父类被润饰成了抽象类, 不能 new, 只能学习父类提供的共性办法
办法
void close()
• void flush()
• void write(byte[] b)
• void write(byte[] b, int off, int len)
• abstract void write(int b)
FileOutputStream
文件输入流是用于将数据写入 File 或 FileDescriptor 的输入流
子类能够应用 父类的办法, 还能应用本人的扩大办法, 还能 new
FileOutputStream(File file)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)
FileOutputStream(File file, boolean append)
BufferedOutputStream 高级流 / 缓冲流
– 该类实现缓冲的输入流
– 创建对象
BufferedOutputStream(OutputStream out)
泛型
概述
因为汇合中增加的元素类型太丰盛.
如果想要限度汇合中元素的类型 , 就要应用泛型.
泛型是(Generics)是 JDK1.5 的一个新个性,其实就是一个『语法糖』. 标记 <>
益处
– 通过泛型的语法定义,束缚汇合元素的类型,进行安全检查,把谬误显示在编译期
– 代码通用性更强。
能够呈现的地位
– 类上 : public class Student<E>{}
– 办法上: public <E> void eat(E d){}
Collection 接口
概述
Collection 层次结构 中的根接口。Collection 示意一组对象,这些对象也称为 collection 的元素。一些 collection 容许有反复的元素,而另一些则不容许。一些 collection 是有序的,而另一些则是无序的
罕用办法
c.clear(); // 清空集合
System.out.println(c.contains(13) );// 判断 c 里蕴含 13 这个元素吗
System.out.println(c.equals(123) );// 判断 c 是否和 123 相等
System.out.println(c.hashCode() );// 获取 c 在内存中的哈希码值
System.out.println(c.isEmpty() );// 判断 c 是否为空
System.out.println(c.remove(2) );// 移除指定的数据
System.out.println(c.size() );// 获取 c 汇合的长度
// 汇合转数组
Object[] os = c.toArray();// 把 c 里的数据存入数组里
System.out.println(c.addAll(c2) );// 把 c2 加到 c 里去
System.out.println(c.containsAll(c2) );// 判断 c 里蕴含 c2 吗
// 移除 c 中那些也蕴含在 c2 中的所有元素
// System.out.println(c.removeAll(c2) );
// 仅保留 c 中那些也蕴含在 c2 的元素
// System.out.println(c.retainAll(c2) );
Iterator<Integer> it = c.iterator();
//hasNext()- 判断汇合里有元素吗, 有元素就获取, 没有就不取.
while(it.hasNext() ){
Integer in = it.next();
//next()- 把元素获取进去
System.out.println(in);
List 子接口
概述
能够应用父接口 Collection 的所有办法. 也能够有本人的扩大办法.
接口不能被 new, 学习提供的共性办法
特点
– 有序
– 可反复
– 能够存多个 null
– 有索引
罕用办法
– 继承自父接口 Collection 的
略 …
!!! 本人扩大的
void add(int index, E element) 在索引处插入新的值
boolean addAll(int index, Collection<? extends E> c)
E get(int index) 获取下标为 index 的元素
int indexOf(Object o) 获取 o 这个元素第一次呈现的索引值
int lastIndexOf(Object o) 获取 o 这个元素最初一次呈现的索引值
E remove(int index) 移出索引处的元素
E set(int index, E element) 在该索引处,增加元素
List<E> subList(int fromIndex, int toIndex)截取一段汇合
ArrayList
概述
是 List 接口的实现类 . 底层用一个 大小可变的数组 来存放数据的.
创建对象
ArrayList() 结构一个初始容量为 10 的空列表。
LinkedList
概述
是 List 接口的链接列表实现.
创建对象
LinkedList() 结构一个空列表。
罕用办法
list.addFirst(“ 钢铁侠 ”);// 增加首元素 list.addLast(“ 灭霸 ”);// 增加尾元素
System.out.println(list.getFirst() );// 获取首元素 System.out.println(list.getLast() );// 获取尾元素
System.out.println(list.removeFirst() );// 移除首元素 System.out.println(list.removeLast() );// 移除尾元素
Set 接口
概述 一个不蕴含反复元素的 collection。特点 – 不能反复 – 没有索引 – 无序
HashSet
概述 此类实现 Set 接口, 底层是一个哈希表。它不保障 set 的迭代程序;特地是它不保 证该程序恒久不变。此类容许应用 null 元素。 创建对象 HashSet() 结构一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75
特点: 元素不能反复 + 数据无序 + 能够存一个 null
Map 接口
概述
map 里的数据都是一个一个的 键值对 , 当向 map 里存储数据时, 须要指定这条数据的 key 和 value 而且,key 不能反复, 如果反复就会把 value 笼罩掉.
罕用办法
public class Test1_Map {public static void main(String[] args) {//1, 创立 map 对象 Map<Integer,String> map = new HashMap(); //2, 调用办法 //TODO map 的特点: 存的数据都是 键值对模式 + 无序 … map.put(9529,” 石榴姐 ”); map.put(9529,” 如花姐姐 ”); map.put(9528,” 秋香姐 ”); map.put(9527,” 唐伯虎 ”);
public static void main(String[] args) {
//1, 创立 map 对象
Map<Integer,String> map = new HashMap();
//2, 调用办法
//TODO map 的特点: 存的数据都是 键值对模式 + 无序 …
map.put(9529,” 石榴姐 ”);
map.put(9529,” 如花姐姐 ”);
map.put(9528,” 秋香姐 ”);
map.put(9527,” 唐伯虎 ”);
System.out.println(map);
// map.clear();// 清空 map 汇合
System.out.println(map.containsKey(9529) );// 判断 map 是否蕴含指定的 key
System.out.println(map.containsValue(“ 唐伯虎 ”) );// 判断 map 是否蕴含指定的 value
System.out.println(map.equals(123) );// 判断 map 和 123 相等吗
System.out.println(map.get(9527) );// 依据 key 去 map 里找 value
System.out.println(map.hashCode() );// 获取哈希码值
System.out.println(map.isEmpty() );// 判断是否为空
System.out.println(map.remove(9529) );// 依据 key 删除记录, 并返回 value
System.out.println(map.size() );// 获取 map 里元素的个数
迭代 map 里的数据: 没提供间接的迭代办法, 须要, 把 map 转成 set, 进而迭代 set 来获取数据.
//TODO 形式 1: Set<K> keySet() — 把 map 里的 key 存入 set
// 思路: 调用办法, 把 map 转成 set.
Set<Integer> set = map.keySet() ;
// 遍历 set 失去每一个 key.
for(Integer key : set){
// 拿着 set 遍历失去的 key 再回 map 里找 value
String value = map.get(key);
System.out.println(key +”======”+value);
}
//TODO 形式 2: Set<Map.Entry<K,V>> entrySet()– 把 map 里的整条记录封装成 Entry 存入 set
// 思路: 调用办法, 把 map 转成 set.
Set<Map.Entry<Integer,String>> set2 = map.entrySet() ;
// 遍历 set 失去每一个 Entry.
for(Map.Entry<Integer,String> entry : set2){
// 再获取 Entry 封装着 key 和 value.
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key +”~~~~”+ value);
}
//TODO 形式 3: Collection<V> values() — 用的少!
Collection<String> values = map.values();
for (String value : values) {
System.out.println(value);
}
HashMap 实现类
概述
底层为了一个哈希表 / 散列表. 底层在存储数据时, 实质上是向桶里增加数据. 默认容量是 16, 当达到 16 的 0.75 阈值后, 再减少的数据 rehash 开拓新空间
创建对象
HashMap() 结构一个具备默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
练习
统计字符串中的字符呈现次数 – 需要: 接管用户输出的一串字符串,统计呈现的每个字符的个数 – 代码 package cn.tedu.api;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
// 测试
// 需要: 接管用户输出的一串字符串,统计呈现的每个字符的个数
public class Test3_HashMap {
public static void main(String[] args) {
//1, 接管用户输出的一串字符串 abcab
String input = new Scanner(System.in).nextLine();
// 定义 map, 用来存储数据 {a=2 ,b=2 ,c=1}
//map 里的 key 是呈现的字符,value 是这个字符呈现了几次
Map<Character,Integer> map = new HashMap();
//2, 遍历字符串, 获取每个字符
for (int i = 0; i < input.length() ; i++) {
char key = input.charAt(i);
//3, 统计每个字符的个数 – 并存入 map {a=2 ,b=2 ,c=1}
Integer value = map.get(key) ;
//value 的值到底存啥? — 如果存过就 +1, 如果没存过就存 1
if(value == null){
value = 1;
}else{
value = value + 1;
}
// 把筹备好的 key 和 value 存入 map
map.put(key,value);
}
System.out.println(map);
}
}
Collections 工具类
概述
此类齐全由在 collection 上进行操作或返回 collection 的静态方法组成。 –2, 罕用办法 static <T> boolean addAll(Collection<? super T> c, T… elements) 将所有指定元素增加到指定 collection 中。 static T min(Collection<? extends T> coll) 依据元素的天然程序 返回给定 collection 的最小元素。 static T max(Collection<? extends T> coll) 依据元素的天然程序 返回给定 collection 的最大元素。 static void reverse(List<?> list) 反转指定列表中元素的程序。 static void sort(List<T> list) 依据元素的天然程序 对指定列表按升序进行排序。 static void swap(List<?> list, int i, int j) 在指定列表的指定地位处替换元素。
测试
package cn.tedu.api;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
// 测试 汇合工具类 Collections
public class Test4_Collections {
public static void main(String[] args) {
// 用工具类前: 向 List 汇合里增加一些元素
List<Integer> list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list);//[1, 2, 3, 4, 5]
// 用工具类后
List<Integer> list2 = new ArrayList();
//TODO 1,addAll()– 用来给指定的 list2 汇合增加一些数据
Collections.addAll(list2,13,65,82,26,39,61);
//[13, 65, 82, 26, 39, 61]
System.out.println(list2);
//TODO 2,max() 求最大值 min()求最小值
System.out.println(Collections.max(list2) );
System.out.println(Collections.min(list2) );
//TODO 3,reverse() 翻转数据
Collections.reverse(list2);
System.out.println(list2);//[61, 39, 26, 82, 65, 13]
//TODO 4,sort() 排序, 默认从小到大
Collections.sort(list2);
System.out.println(list2);//[13, 26, 39, 61, 65, 82]
//TODO 5,swap() 替换指定地位的两个元素
Collections.swap(list2,1,4);
System.out.println(list2);//[13, 65, 39, 61, 26, 82]
}
}
多线程
概念
– 过程和线程的区别 — 过程是 正在运行的程序 — 线程是 零碎能够调度的最小单位, 是过程的理论运作单位 一个软件运行 须要依赖多个过程, 一个过程的运行能够依赖多个线程 – 并行和并发的区别 – 并发是 多个资源 抢占 CPU, 让 CPU 去干活 – 并行是 多个资源要干活, 只不过有多个 CPU 去干活, 基本没产生抢的景象 多线程是 为了进步程序的执行效率, 是指相当于 把一件事分给 10 集体, 抢着干 — 并发
多线程编程
Thread 类
– 创建对象 Thread() 调配新的 Thread 对象。 Thread(Runnable target) 调配新的 Thread 对象。 Thread(Runnable target, String name) 调配新的 Thread 对象。 Thread(String name) 调配新的 Thread 对象。 – 罕用办法 static Thread currentThread() 返回对以后正在执行的线程对象的援用。 long getId() 返回该线程的标识符。 String getName() 返回该线程的名称。 void run() 如果该线程是应用独立的 Runnable 运行对象结构的,则调用该 Runnable 对象的 run 办法; void setName(String name) 扭转线程名称,使之与参数 name 雷同。 static void sleep(long millis) 在指定的毫秒数内让以后正在执行的线程休眠 void start() 使该线程开始执行;Java 虚拟机调用该线程的 run 办法。 void stop() 已过期。该办法具备固有的不安全性。用 Thread.stop 来终止线程
模仿多线程编程
– 继承 Thread 类
package cn.tedu.thread;
// 模仿多线程编程
public class Test2_Thread {
public static void main(String[] args) {
//4, 创建对象 MyThread 测试
MyThread t = new MyThread();
t.setName(“ 杨幂 ”);// 批改线程名称
// t.run();// 只是一个一般的办法调用, 并不能实现多线程的抢占成果. 只是程序执行
t.start();//TODO 6, 是真正的开启线程, 产生随机性的特点
• //TODO 5, 模仿多线程 >= 2
• MyThread t2 = new MyThread();
• t2.setName(“Anglelababa”);
• // t2.run();
• t2.start();
• /* 7, 测试失去的后果展现了多线程程序执行的随机性特点: 两个线程始终在抢占 CPU 的执行权
• Thread-0====9
• Thread-0====10
• Thread-1====1
• Thread-0====11
• Thread-1====2
• Thread-0====12
• Thread-1====3
• Thread-0====13
• */
• }
• }
• //1, 创立自定义的线程类 — 继承 Thread 类
• class MyThread extends Thread{
• //2, 多线程的所有业务代码 , 放入重写的 run() 里 – 右键..generate..override methods..ok
• @Override
• public void run() {
• // super.run();
• //TODO 3, 需要: 打印 50 次线程名称
• for (int i = 0; i < 50; i++) {
• System.out.println(super.getName() +”====”+i );
• }
• }
• }
同步锁
- 把有问题的代码加锁 – 同步锁 — 同步是指没钥匙就排队期待的状态. 锁是指把操作共享资源的代码锁起来 — 通过 sychronized 关键字实现
一般办法 会主动调配默认的锁对象 是 this
静态方法 的锁对象会主动调配 是类名.class
如果是一般资源, 锁对象任意只有是同一个锁对象就能够
如果是动态资源, 锁对象 必须是 类名.class
语法
– 能够用在办法上 — public synchronized void append() { – 能够用在代码块上 — synchronized(锁对象){// 这个对象能够任意, 然而, 必须是同一个对象 有问题的代码 }
设计模式
概述
软件设计模式(Design pattern),又称设计模式,是一套被重复应用、少数人通晓的、通过 分类编目标、代码设计教训的总结。应用设计模式是为了可重用代码、让代码更容易被别人了解、保障代码可靠性、程序的重用性。
单例模式(Singleton)
保障一个类仅有一个实例,并提供一个拜访它的全局拜访点。模仿单例设计模式
package cn.tedu.design;
• // 模仿 – 23 种设计模式里的 单例设计模式 – 保障一个类仅有一个对象
• // 单例模式 :
• //1, 私有化构造方法, 不能让外界随便 new
• //2, 在类的外部, 本人 new 好一个对象, 让外界用
• //3, 提供一个全局的拜访点 get(), 用来获取 new 好的对象
• // 益处是 : 管制外界 new 的权力, 节俭内存节省时间 –SSM 大量应用
• public class Test1_Singleton {
• public static void main(String[] args) {
• Person p1 = Person.getP();//5, 调用静态方法, 应用对象
• Person p2 = Person.getP();
• System.out.println(p1 == p2);//true
• Student s1 = Student.getS();
• Student s2 = Student.getS();
• System.out.println(s1 == s2);//true
• }
• }
懒汉式 – 面试的重点!!! — 提早加载 + 线程不平安
class Student{
//1, 私有化结构
private Student(){}
//2, 本人申明一个对象
static private Student s ; //null
//3, 对外提供的一个 get()
synchronized static public Student getS() {
// 4, 在多线程编程中, 共享资源 s, 被多条语句操作, 肯定会有安全隐患 — 必须加锁
// 锁加在 同步办法或者同步代码块都能够,
// 如果共享资源是动态资源, 那么, 锁对象必须 固定是 类名.class
// 如果办法是一般办法锁对象默认是 this, 如果是动态方锁对象默认是类名.class
// synchronized (Student.class){
if(s == null){
// 如果是默认值 null, 就创建对象 – 保障了单例!!
s = new Student();
}
return s;
// }
}
}
饿汉式 – 学习工作中应用的形式!!!
class Person{
//1, 私有化构造方法 — 不让外界轻易 new
private Person(){}
• //2, 在 类的外部 提供一个 new 好的对象
• // 加 static — 因为动态只能调用动态, 所以, 想要被动态的 getP() 调用, 必须润饰成动态的
• static private Person p = new Person();
• //3, 提供公共的拜访形式 getXxx(), 获取 p 对象
• // 加 static — 目前无奈通过创建对象来调用 getP(), 所以变成动态的, 间接通过类名来调用 getP()
• static public Person getP(){
• return p ;// 把创立好的对象 p, 返回给调用地位
• }
• }
反射
概述
Reflection(反射) 是 Java 程序开发语言的特色之一,它容许运行中的 Java 程序对本身 进行查看,或者说“自审”,也有称作“自省”。反射十分弱小,它甚至能间接操作程序的公有属性。咱们后面学习都有一个概念,private 的只能类外部拜访,内部是不行的,但这个规定被反射 赤裸裸的突破了。
反射就像一面镜子,它能够在运行时获取一个类的所有信息,能够获取到任何定义的信息(包 括成员变量,成员办法,结构器等),并且能够操纵类的字段、办法、结构器等局部。– 实质 JVM 利用反射技术, 来解析.class 文件里的所有数据, 包含 公开的和公有的 成员变量 / 成员方 法 / 构造方法 /….. 并把所有获取到的资源, 封装起来造成 Class 工具类. 而后通过 Class 工具类提供了各种办法来解析获取各种 … – 开发思路 – 获取 Class 对象 – 通过 Class 工具类提供的各种办法来后去所有资源 – 获取 Class 对象的形式 –Class.forName(“类的全门路”); – 类名.class – 对象.getClass();
创立 Demo 类
package cn.tedu.reflect;
import org.junit.Test;
// 测试 反射
public class Demo {
public Demo(){}
public Demo(String name) {
this.name = name;
}
public Demo(String name, int age) {
this.name = name;
this.age = age;
}
public String name;
public int age;
@Test
public void show(){
System.out.println(“show”);
}
public void save(int id){
System.out.println(“ 保留胜利!”);
}
}
创立测试类
package cn.tedu.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
// 反射 Demo 类里的资源
// 总结
// 原理是 :
//1, 通过 类的加载器 把 java 里的类, 加载进内存. 而后通过编译器, 把.java 文件编译变成.class 文件
//2,JVM 拿到你的.class 文件, 开始解析外面的所有资源 . 把.class 文件封装成 Class 对象
//3, 通过 Class 工具类提供的各种 getXxx() 获取各种资源
• // 用过 Class 工具类的办法:
• //1,getConstructors() — 获取所有的 公开的 构造方法们~~~
• //2,getFields() — 获取所有的 公开的 成员变量们~~~
• //3,getMethods() — 获取所有的 公开的 成员办法们~~~
• public class Test1_Reflect {
• public static void main(String[] args) throws Exception {
• // method();// 反射.class 里的构造方法
• // method2();// 反射.class 里的 一般办法
• // method3();// 反射.class 里的 成员变量
• method4();// 利用反射创建对象
• }
• // 利用反射创建对象
• public static void method4() throws Exception {
• //1, 反射 Class 对象
• Class a = Demo.class;
• //2, 创建对象
• //newInstance() 默认返回的是 Object 父类类型
• Object d = a.newInstance();// 默认会触发无参结构
• // Demo d = (Demo)a.newInstance(); 为了用子类的特有性能
• //cn.tedu.reflect.Demo@677327b6
• System.out.println(d);
• }
• // 反射.class 里的 成员变量
• public static void method3() {
• //1, 获取 Class 对象
• Class a = Demo.class;
• //2, 获取 所有 公共的 成员变量们~
• Field[] fs = a.getFields();
• //3, 获取每个 成员变量 f
• for (Field f : fs) {
• //4, 获取 变量名
• System.out.println(f.getName() );
• //5, 获取 变量类型
• System.out.println(f.getType().getName());
• }
• }
• // 反射.class 里的 一般办法
• public static void method2() {
• //1, 获取 Class 对象
• Class a = Demo.class;
• //2, 反射所有 公开的 办法们~~~
• // 本人的和父类的
• Method[] ms = a.getMethods();
• //3, 获取 每个办法 m
• for (Method m : ms) {
• //4, 获取 办法名
• System.out.println(m.getName() );
• //5, 获取 办法的参数类型
• Class[] css = m.getParameterTypes();
• System.out.println(Arrays.toString(css) );
• }
• }
• //TODO 反射.class 文件里的 构造方法
• public static void method() {
• //1, 反射 class 对象
• Class a = Demo.class ;
• //2, 获取所有 构造方法们 ~
• Constructor[] cs = a.getConstructors();
• //3, 获取每个构造方法 x
• for(Constructor x : cs){
• //4, 获取 x 的 参数类型们 ~
• Class[] css = x.getParameterTypes();
• System.out.println(Arrays.toString(css) );
• }
• }
• }
暴力反射
概述
把.class 文件里的 所有数据获取到. 包含 public 的 和 private 的 新的 API getDeclaredFields() — 获取 所有 成员变量 getDeclaredField() — 获取 指定的 成员变量 getDeclaredMethods() — 获取 所有 成员办法 getDeclaredMethod() — 获取 指定的 成员办法 getDeclaredConstructors() — 获取 所有 构造方法 getDeclaredConstructor() — 获取 指定的 构造方法
创立 Student 类
package cn.tedu.reflect;
import org.junit.Test;
// 测试 暴力反射
public class Student {
public String name;
private int age ;
• public void show(){
• System.out.println(“show()”);
• }
• public void save(int a){
• System.out.println(“ 保留胜利!”);
• }
• private void get(String a){
• System.out.println(“ 保留胜利!”+a);
• }
• private void delete(int id){
• System.out.println(“ 删除胜利!”+id);
• }
}
创立测试类
package cn.tedu.reflect;
• import org.junit.Test;
• import java.lang.reflect.Field;
• import java.lang.reflect.Method;
• import java.util.Arrays;
• // 测试 暴力反射
• // 总结:
• //1, 暴力反射 能够获取.class 文件里的 public 和 private 资源
•
• public class Test2_Baoli {
• public static void main(String[] args) throws Exception {
• // method();// 暴力反射 所有成员办法
• // method2();// 暴力喷射 指定办法并执行
• // method3();// 练习
• // method4();// 暴力反射 所有成员变量
• // method5();// 暴力反射 指定成员变量
• method6();// 执行 注解办法
• }
•
private static void method6() throws Exception {
• //1, 获取 Class 对象
• Class a = Student.class;
• Object o = a.newInstance();
• //2, 获取所有办法
• Method[] ms = a.getDeclaredMethods();
• //3, 遍历失去每个办法 m
• for (Method m : ms) {
• //4, 获取 指定的 Test 注解 – 参数就是注解的 Class
• Test test = m.getDeclaredAnnotation(Test.class);
• //5, 判断哪些有 就 invoke() 执行
• if(test != null){
• //invoke(m,n)- m 是对象名 - n 是要给办法传递的参数
• m.invoke(o,null);
• }
• }
• }
//TODO 暴力反射 指定成员变量
• private static void method5() throws Exception {
• Class a = Student.class;
• //1, 依据变量名获取 指定的变量 f
• Field f = a.getDeclaredField(“age”);
• f.setAccessible(true);// 设置公有的拜访权限!!!
• //2,set() 设置值
• // 第一个参数是 指定的对象名 第二个参数是 要给属性设置的值
• Object o = a.newInstance();
• f.set(o,100);
• //3,get() 获取值 — 须要指定要获取哪个对象的
• System.out.println(f.get(o) );
• }
// 暴力反射 所有成员变量
• private static void method4() {
• //1, 获取 Class 对象
• Class a = Student.class;
• //2, 获取 所有 成员变量们~
• Field[] fs = a.getDeclaredFields();
• //3, 获取每个 成员变量 f
• for (Field f : fs) {
• //4, 获取 变量名
• System.out.println(f.getName() );
• //5, 获取 变量类型
• System.out.println(f.getType().getName());
• }
• }
public static void method3() throws Exception {
• Class a = Student.class;
• Method m = a.getDeclaredMethod(“delete”, int.class);
• m.setAccessible(true);// 设置公有的拜访权限
• Object o = a.newInstance();
• m.invoke(o,10);// 执行指定办法
• }
•
// 暴力喷射 指定办法并执行
• public static void method2() throws Exception {
• //1, 获取 Class 对象
• Class a = Student.class;
• //2, 获取指定的某个办法
• // 第一个参数是 指定的办法名称
• // 第二个参数是 该办法须要的参数类型的 Class 对象
• Method m = a.getDeclaredMethod(“get”,String.class) ;
• m.setAccessible(true);// 开启拜访权限!!!!!!!
• //3, 让办法执行起来 invoke
• // 第一个参数是 指定对象
• // 第二个参数是 指定给该办法传入的参数
• Object o = a.newInstance();
• m.invoke(o,”hello”);
• }
//TODO 暴力反射成员办法 getDeclaredMethods()
• public static void method() {
• //1, 获取 Class 对象
• Class a = Student.class;
• //2, 反射所有 办法们~~~
• Method[] ms = a.getDeclaredMethods();
• //3, 获取 每个办法 m
• for (Method m : ms) {
• //4, 获取 办法名
• System.out.println(m.getName() );
• //5, 获取 办法的参数类型
• Class[] css = m.getParameterTypes();
• System.out.println(Arrays.toString(css) );
• }
• }
• }
反射的练习
创立 Person 类
// 练习反射
public class Person {
String name;
private int age ;
public void save(int id){
System.out.println(“save..”+id);
}
private void delete(int id){
System.out.println(“delete..”+id);
}
}
创立测试类
import java.lang.reflect.Field;
import java.lang.reflect.Method;
// 练习反射
public class Test3_Person {
public static void main(String[] args) throws Exception {
// 获取 Class 对象
Class a = Person.class ;
// method(a);// 反射属性并 set()/get()
method2(a);// 反射办法并运行
}
// 反射办法并运行
private static void method2(Class m) throws Exception {
// 反射 指定的 公有办法
Method me = m.getDeclaredMethod(“delete”,int.class);
// 设置拜访权限 !!!!
me.setAccessible(true);
// 执行办法
Object o = m.newInstance();
me.invoke(o,200);
}
// 反射属性并 set()/get()
private static void method(Class m) throws Exception {
// 属性被封装无奈间接用, 能够通过反射操作 ~~~
// new Person().age = 20 ;
// 反射 指定名称的 属性
Field f = m.getDeclaredField(“age”);
// 设置公有的拜访权限 !!!!
f.setAccessible(true);
// 利用反射创建对象
Object o = m.newInstance();
// 给属性设置具体值
f.set(o,66);
// 获取属性值
System.out.println(f.get(o) );
}
}
外部类
概述
外部类 是为了 给外部类服务的. 构造 class A{// 外部类
class B{// 外部类 — 看做是 A 类的一个非凡的成员 } } 特点 – 外部类 随着地位的不同, 名字和作用都不同 – 在成员地位 (类里办法外) 的外部类, 叫成员外部类 – 在部分地位 (办法里) 的外部类, 叫部分外部类 – 在内部类 应用 外部类的资源 – 间接应用 – 在外部类 应用 外部类的资源 — 创立外部类对象拜访 !!
入门案例
package cn.tedu.inner;
// 测试 外部类
public class Test3_Inner {
public static void main(String[] args) {
//1, 想用外部类的资源 – 创立外部类的对象
// 外部类名. 外部类名 变量名 = 外部类对象. 外部类对象
Outer.Inner oi = new Outer().new Inner();
System.out.println(oi.age);
oi.in();
}
}
class Outer{// 外部类
String name ;
public void out(){
//TODO 3, 在外部类 应用 外部类的资源 — 创立外部类对象拜访 !!
System.out.println(new Inner().age );
System.out.println(“out..”);
}
class Inner{// 外部类 – 在成员地位的外部类是成员外部类
int age;
public void in(){
//TODO 2, 在内部类 应用 外部类的资源 – 间接应用
out();
System.out.println(“in..”);
}
}
}
匿名外部类
public class Test4_Inner {
public static void main(String[] args) {
new Inter(){// 相当于创立了接口的对象
@Override// 重写了接口里的办法
public void save() {
System.out.println(“save()”);
}
}.save();// 调用了指定的办法
//TODO
new Inter2(){
@Override
public void update(int id) {
System.out.println(“ 更新数据胜利,id 是:”+id);
}
}.update(10);
//TODO
Inter3 in = new Inter3(){
@Override
public void update(int id) {
System.out.println(“ 更新胜利,id 是:”+id);
}
@Override
public void delete(int id) {
System.out.println(“ 删除胜利,id 是:”+id);
}
};
in.delete(10); // 匿名对象干一个活儿, 那就给对象起个名字干好多活儿
in.update(5);
interface Inter{
// 能够简写, 会主动拼接 public abstract
void save();
}
interface Inter2{
void update(int id);
}
interface Inter3{
void update(int id);
void delete(int id);
}