API专题
Posted PearSakura
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了API专题相关的知识,希望对你有一定的参考价值。
概述
一切可以调用的都是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);
}
以上是关于API专题的主要内容,如果未能解决你的问题,请参考以下文章