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{}

--方法上: public 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 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 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 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 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 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 keySet() -- 把map里的key存入set
  //思路:调用方法,把map转成set.
  Set 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> entrySet()--把map里的整条记录封装成Entry存入set
  //思路:调用方法,把map转成set.
  Set> set2 = map.entrySet() ;
  // 遍历set得到每一个Entry.
  for(Map.Entry entry : set2){
  // 再获取Entry封装着key和value.
  Integer key = entry.getKey();
  String value = entry.getValue();
  System.out.println(key +"~~~~"+ value);
  }
  //TODO 方式3: Collection values() -- 用的少!
  Collection 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 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 boolean addAll(Collection c, T... elements) ​ 将所有指定元素添加到指定 collection 中。 ​ static T min(Collection coll) ​ 根据元素的自然顺序 返回给定 collection 的最小元素。 ​ static T max(Collection coll) ​ 根据元素的自然顺序 返回给定 collection 的最大元素。 ​ static void reverse(List list) ​ 反转指定列表中元素的顺序。 ​ static void sort(List 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 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 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);
  }

你可能感兴趣的:(java)