Java学习笔记 一、数组 1、遍历数组
1 2 3 4 5 6 7 8 9 10 11 public class Deo { public static void main (String[] args) { int b[][]={{1 }.{2 ,3 },{4 ,5 ,6 }}; for (int k=0 ;k<b.length;k++){ for (int c=0 ;c<b[k].length;c++){ System.out.print(b[k][c]); } System.out.println(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class deo { public static void main (String[] args) { int arr[][]= {{4 ,3 },{2 ,1 }}; System.out.println("数组中的元素是:" ); int i=0 ; for (int x[]:arr) { i++; int j=0 ; for (int e:x) { j++; if (i==arr.length&&j==x.length) { System.out.print(e); }else { System.out.print(e+"、" ); } } } } }
2、填充替换数组元素
fill(int [] arr,int value);
1.arr:要进行填充的数组;
2.value:要存储数组中所有元素的值
1 2 3 4 5 6 7 8 9 10 11 12 13 import java.util.Arrays; public class swap { public static void main (String[] args) { int arr[]=new int [5 ]; Arrays.fill(arr, 8 ); for (int i=0 ;i<arr.length;i++) { System.out.println("第" +(i+1 )+"个元素的值是:" +arr[i]); } } }
fill(int[] arr,int from,int to,int value);
1.arr:要进行填充的数组;
2.from:要使用指定值填充的第一个元素的索引(包括);
3.to:要使用指定值填充的最后一个元素的索引(不包括);
4.value:要分配给数组指定范围中的每个元素的值.
1 2 3 4 5 6 7 8 9 10 11 12 13 import java.util.Arrays;public class swap { public static void main (String[] args) { int arr[]={5 ,4 ,2 ,1 ,2 }; Arrays.fill(arr,1 ,3 , 8 ); for (int i=0 ;i<arr.length;i++) { System.out.println("第" +(i+1 )+"个元素的值是:" +arr[i]); } } }
3、对数组进行排序 Arrays.sort(object);
object为需要进行排序的数组名称.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import java.util.Arrays;public class swap { public static void main (String[] args) { int arr[]={5 ,4 ,2 ,1 ,2 }; Arrays.fill(arr,1 ,3 , 8 ); Arrays.sort(arr); for (int i=0 ;i<arr.length;i++) { System.out.println("第" +(i+1 )+"个元素的值是:" +arr[i]); } } }
冒泡排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class BubbleSort { public static void main (String[] args) { int []arr=new int [] {12 ,23 ,43 ,54 ,65 }; BubbleSort sorter=new BubbleSort (); sorter.sort(arr); } public void sort (int []arr) { for (int i=1 ;i<arr.length;i++) { for (int j=0 ;j<arr.length-i;j++) { if (arr[j]>arr[j+1 ]) { int temp=arr[j]; arr[j]=arr[j+1 ]; arr[j+1 ]=temp; } } } for (int i:arr) { System.out.print(">" +i); } System.out.println(); } }
直接选择排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class SelectSort { public static void main (String[] args) { int []arr= {43 ,32 ,4 ,5 ,67 ,7 }; sort(arr); } public static void sort (int arr[]) { int index; for (int i=1 ;i<arr.length;i++) { index=0 ; for (int j=1 ;j<=arr.length-i;j++) { if (arr[j]>arr[index]) { index=j; } } int temp=arr[arr.length-i]; arr[arr.length-i]=arr[index]; arr[index]=temp; } for (int i:arr) { System.out.print(">" +i); } System.out.println(); } }
反转排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class ReverseSort { public static void main (String[] args) { int arr[]= {11 ,22 ,33 ,44 ,55 ,66 ,77 }; sort(arr); } public static void sort (int []arr) { System.out.println("原数组元素内容为:" ); for (int i:arr) { System.out.print(">" +i); } System.out.println(); int temp,len=arr.length; for (int i=0 ;i<len/2 ;i++) { temp=arr[i]; arr[i]=arr[len-i-1 ]; arr[len-1 -i]=temp; } System.out.println("新数组元素内容为:" ); for (int i:arr) { System.out.print(">" +i); } System.out.println(); }
4、复制数组 copyOf(arr,int newlength);
arr:要进行复制的数组;
newlength:int型常量,指复制后的新数组的长度。如果新数组长度大于原数组长度,则用0(null)来填充;
若小于原数组长度,则会从原数组的第一个元素开始截取至满足新数组长度为止。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import java.util.Arrays;public class swap { public static void main (String[] args) { int arr[]={5 ,4 ,2 ,1 ,2 }; int arr2[]=Arrays.copyOf(arr,3 ); int arr3[]=Arrays.copyOf(arr, 10 ); for (int i=0 ;i<arr.length;i++) { System.out.println("第" +(i+1 )+"个元素的值是:" +arr[i]); } System.out.println("----------------" ); for (int i=0 ;i<arr2.length;i++) { System.out.println("第" +(i+1 )+"个元素的值是:" +arr2[i]); } System.out.println("----------------" ); for (int i=0 ;i<arr3.length;i++) { System.out.println("第" +(i+1 )+"个元素的值是:" +arr3[i]); } System.out.println("----------------" ); } }
copyOfRange(arr,int from,int to);
arr:要复制的数组
from:指开始复制数组的索引位置(包括);
to:指开始复制数组的结束索引位置(不包括);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class swap { public static void main (String[] args) { int arr[]={5 ,4 ,2 ,1 ,2 }; int arr2[]=Arrays.copyOfRange(arr,0 ,3 ); int arr3[]=Arrays.copyOfRange(arr,0 ,10 ); for (int i=0 ;i<arr.length;i++) { System.out.println("第" +(i+1 )+"个元素的值是:" +arr[i]); } System.out.println("----------------" ); for (int i=0 ;i<arr2.length;i++) { System.out.println("第" +(i+1 )+"个元素的值是:" +arr2[i]); } System.out.println("----------------" ); for (int i=0 ;i<arr3.length;i++) { System.out.println("第" +(i+1 )+"个元素的值是:" +arr3[i]); } System.out.println("----------------" ); } }
5、查询数组 binarySearch(Object[] arr, Object value); //返回的是搜素值得索引,否则返回-1或‘ - ’(插入点);
arr:要搜素的数组;
value:要搜素的值.
1 2 3 4 5 6 7 8 9 10 11 12 import java.util.Arrays;public class swap { public static void main (String[] args) { int arr[]={5 ,4 ,2 ,1 ,3 }; int index=Arrays.binarySearch(arr, 3 ); System.out.println("3的索引位置是:" +index); int index2=Arrays.binarySearch(arr, 11 ); System.out.println("11的索引位置是:" +index2+"(数组中未找到该元素)" ); } }
binarySearch(object[] arr,int from,int to,int value);
arr:要进行检索的数组;
from:指定范围检索的开始处索引(包括);
to:指定范围检索的结束处索引(不包括);
value:要搜素的值.
1 2 3 4 5 6 7 8 9 10 11 import java.util.Arrays;public class swap { public static void main (String[] args) { int arr[]={5 ,4 ,2 ,1 ,3 }; int index=Arrays.binarySearch(arr,0 ,5 , 3 ); System.out.println("3的索引位置是:" +index); int index2=Arrays.binarySearch(arr,0 ,5 , 11 ); System.out.println("11的索引位置是:" +index2+"(数组中未找到该元素)" ); } }
二、字符串 单个字符可以用char类型保存,多个字符组成的文本就需要保存在String对象中。String通常称为字符串,一个String对象最多可以保存2^32-1个字节(占用4GB空间大小)的文本内容。
1、声明、创建字符串 1 2 3 4 5 6 7 8 9 10 11 12 String str; char a[]={'g' ,'o' ,'o' ,'d' };String s=new String (a); char a[]=['s' ,'t' ,'u' ,'d' ,'e' ,'n' ,'t' ];String s=new String (a,2 ,4 ); String str1; str1="Student" ;
2、连接字符串 1 2 3 4 5 6 7 8 9 10 11 12 public class Link { public static void main (String[] args) { String str1=new String ("春色绿千里" ); String str2=new String ("马蹄香万家" ); String s=str1+"\n" +str2; System.out.println(s); int booktime=4 ; float practice=6.5f ; System.out.println("我每天花费" +booktime+"小时看书;" +practice+"小时上机训练" ); } }
3、获取字符串信息
使用String类的length()方法可以获取声明的字符串对象的长度.
indexOf(String s);//该方法返回参数字符串s在指定字符串中首次出现的索引位置。若未找到字符串s,则会返回-1.
lastIndexOf(String str);//该方法返回参数字符串s在指定字符串中最后一次出现的索引位置。若未找到字符串s,则会返回-1.
charAt(int index)方法可以将指定索引处的字符返回。
1 2 3 4 5 6 7 8 9 10 11 12 String str="We are student" ; int size=str.length();String str="We are student" ; int index=str.indexOf("a" );int index2=str.lastIndexOf("a" );String str="hello world" ; char mychar=str.chatAt(2 );
4、字符串操作
substring(int begin);
该方法返回的是从指定的索引位置开始截取到该字符串结尾的子串
substring(int begin,int end);
该方法返回的是从字符串某一索引位置开始截取到某一索引位置结束的子串。
1 2 3 4 5 String sub1=str.substring(2 ); String sub2=str.substring(1 ,2 ); System.out.println(sub1); System.out.println(sub2);
trim();
该方法返回字符串的副本,忽略掉前导空格和后导空格。
1 2 3 4 String s=" Java 学习 " ; System.out.println(s.length()); System.out.println(s.trim().length());
replace(target, replacement);
该方法可以实现将指定的字符或字符串替换成新的字符或字符串。
target:要替换的字符或字符串
replacement:用于替换原来字符串的内容
1 2 3 4 String s1="helloworld" ; String s2=s1.replace( "l" ,"L" ); System.out.println(s2);
startWith(String prefix);
该方法判断当前字符串对象的前缀是否为参数指定的字符串。
prefix是指作为前缀的字符串。
endWith(String suffix);
该方法用于判断当前字符串是否以给定的字符串结束。
suffix是指作为后缀的字符串。
1 2 3 4 5 6 7 String num1="22045612" ; String num2="21304578" ; boolean flag1=num1.startsWith("22" ); boolean flag2=num2.endsWith("11" ); System.out.println("字符串num1是以'22'开始的吗?" +flag1); System.out.println("字符串num2是以'11'结束的吗?" +flag2);
equals(String str);
该方法用于判断两个字符串是否相等,且区分大小写,返回的是boolean类型。
equalsLgnoreCase(String str);
该方法用于判断两个字符串是否相等,忽略字母的大小写,返回的是boolean类型。
1 2 3 4 5 6 7 8 String sh1="helloworld" ; String sh2="HElloworld" ; boolean a1=sh1.equals(sh2); boolean a2=sh1.equalsIgnoreCase(sh2); System.out.println(a1); System.out.println(a2);
compareTo(String str);
该方法按照字典顺序比较两个字符串,若按照字典顺序此String对象位于参数字符串之前则返回一个负整数,位于之后,则返回一个正整数,如果两个字符串相同则返回0.
1 2 3 4 5 String sa1="hello" ; String sa2="hallo" ; int compare=sa1.compareTo(sa2); System.out.println(compare);
toLowerCase();
将字符串中所有大写字母转化为小写字母;
toUpperCase();
将字符串中所有小写字母转化为大写字母
1 2 3 4 5 6 sa1="heelll" ; String ss=sa1.toUpperCase(); String sss=ss.toLowerCase(); System.out.println(ss); System.out.println(sss);
1.split(String sign);
该方法可以将给定的分割符对字符串进行拆分,其中sign为分割字符串的分割符。
2.split(String sign,int limit);
该方法可以根据给定的分割符对字符串进行拆分,并限定拆分的次数,其中sign为分割字符串的分割符,limit为限制的拆分次数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 str="192.168.0.1" ; String[]firstArray=str.split("\\." ); String[]secondArray=str.split("\\." ,2 ); System.out.println("str的原值为:[" +str+"]" ); System.out.print("全部分割后的结果为:" ); for (String a:firstArray) { System.out.print("[" +a+"]" ); } System.out.println(); System.out.print("分割两次后的结果为:" ); for (String a:secondArray) { System.out.print("[" +a+"]" ); } System.out.println();
5、字符串生成器 如果对字符串进行拼接操作,每次拼接,都会构建一个新的String对象,既耗时,又浪费内存空间,而这种操作还不可避免。因此我们可以通过StringBuild类来解决这个问题。
StringBuilder是一个可变的字符串类,我们可以把它看作一个容器,这里的可变指的是StringBuilder对象中的内容是可变的
StringBuilder和String的区别:
StringBuilder:内容是可变的
String:内容是不变的
构造方法 public StringBuilder(); 创建一个空白可变字符串对象,不含任何内容
public StringBuilder(String str); 根据字符串的内容,来创建可变字符串对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Builder { public static void main (String[] args) { StringBuilder sb=new StringBuilder (); System.out.println("sb:" +sb); System.out.println("sb.length():" +sb.length()); StringBuilder sb2=new StringBuilder ("hello" ); System.out.println("sb2:" +sb2); System.out.println("sb2.length():" +sb2.length()); } }
添加和反转方法 public StringBuilder append(任意类型) ; 添加数据,并返回对象本身
public StringBuilder reverse(); 返回相反的字符序列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Builder { public static void main (String[] args) { StringBuilder sb=new StringBuilder (); StringBuilder sb2=sb.append("hello" ); System.out.println("sb2:" +sb2); System.out.println("sb2.length():" +sb2.length()); sb.append("java" ); sb.append(" good " ).append("C++ " ); System.out.println("sb:" +sb); System.out.println("sb.length():" +sb.length()); sb.reverse(); System.out.println("sb:" +sb); System.out.println("sb.length():" +sb.length()); } }
StringBuilder和String的相互转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package StringTest;public class zhuanhuan { public static void main (String[] args) { StringBuilder sb=new StringBuilder (); sb.append("Hello" ); String str=sb.toString(); System.out.println(str); String temp="java" ; StringBuilder temp2=new StringBuilder (temp); System.out.println(temp2); } }
6、正则表达式 正则表达式可以检验字符串是否满足一定的规则,并用来校验数据格式的合法性。
作用:
校验字符串是否满足规则
在一段文本中查找满足要求的内容
字符类(只匹配一个字符)
表达式
说明
[abc]
只能是a,b,c
[^abc]
除了a,b,c之外的任何字符
[a-zA-Z]
a到z,A到Z,包括(范围)
[a-d[m-p]]
a到d或者m到p
[a-z&&[def]]
a-z和def的交集,为:d,e,f
[a-z&&[^bc]]
a-z和非bc的交集。等同于[ad-z]
[a-z&&[^m-p]]
a到z除了m到p的交集。等同于[a-lq-z]]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 package Regex;public class RegexDemo2 { public static void main (String[] args) { System.out.println("--------1--------" ); System.out.println("a" .matches("[abc]" )); System.out.println("z" .matches("[abc]" )); System.out.println("ab" .matches("[abc]" )); System.out.println("--------2---------" ); System.out.println("a" .matches("[^abc]" )); System.out.println("z" .matches("[^abc]" )); System.out.println("zz" .matches("[^abc]" )); System.out.println("zz" .matches("[^abc][^abc]" )); System.out.println("--------3--------" ); System.out.println("a" .matches("[a-zA-Z]" )); System.out.println("z" .matches("[a-zA-Z]" )); System.out.println("aa" .matches("[a-zA-Z]" )); System.out.println("zz" .matches("[a-zA-Z]" )); System.out.println("0" .matches("[a-zA-Z]" )); System.out.println("--------4--------" ); System.out.println("a" .matches("[a-d[m-p]]" )); System.out.println("d" .matches("[a-d[m-p]]" )); System.out.println("m" .matches("[a-d[m-p]]" )); System.out.println("p" .matches("[a-d[m-p]]" )); System.out.println("e" .matches("[a-d[m-p]]" )); System.out.println("0" .matches("[a-d[m-p]]" )); System.out.println("--------5---------" ); System.out.println("a" .matches("[a-z&[def]]" )); System.out.println("&" .matches("[a-z&[def]]" )); System.out.println("a" .matches("[a-z&&[def]]" )); System.out.println("d" .matches("[a-z&&[def]]" )); System.out.println("--------6--------" ); System.out.println("a" .matches("[a-z&&[^bc]]" )); System.out.println("b" .matches("[a-z&&[^bc]]" )); System.out.println("d" .matches("[a-z&&[^bc]]" )); System.out.println("0" .matches("[a-z&&[^bc]]" )); System.out.println("--------7--------" ); System.out.println("a" .matches("[a-z&&[^m-p]]" )); System.out.println("m" .matches("[a-z&&[^m-p]]" )); System.out.println("0" .matches("[a-z&&[^m-p]]" )); } }
预定义字符(只匹配一个字符)
表达式
说明
.
任何字符
\d
一个数字:[0-9]
\D
非数字:[^0-9]
\s
一个空白字符[\t\n\x0B\f\r]
\S
非空白字符[^\s]
\w
[a-zA-Z_0-9] 英文、数字、下划线
\W
[^\w] 一个非单词字符
数量词
X? X,一次或0次
X* X,零次或多次
X+ X,一次或多次
X{n} X,至少n次
X{n,m} 至少n但不超过m次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package Regex;public class RegexDemo3 { public static void main (String[] args) { System.out.println("你" .matches(".." )); System.out.println("你a" .matches(".." )); System.out.println("a" .matches("\\d" )); System.out.println("0" .matches("\\d" )); System.out.println("22" .matches("\\d" )); System.out.println("0" .matches("\\w" )); System.out.println("a" .matches("\\w" )); System.out.println("_" .matches("\\w" )); System.out.println("W" .matches("\\w" )); System.out.println("1w" .matches("\\w" )); System.out.println("你" .matches("\\W" )); System.out.println("----------------" ); System.out.println("22138ws32" .matches("\\w{6,}" )); System.out.println("23_f" .matches("\\w{6,}" )); System.out.println("23dF" .matches("[a-zA-Z_0-9]{4}" )); System.out.println("23_F" .matches("[a-zA-Z0-9]{4}" )); System.out.println("23df" .matches("[\\w&&[^_]]{4}" )); System.out.println("23_F" .matches("\\w&&[^-]{4}" )); } }
三、ArrayList 1.ArrayList的构造与添加方法 ArrayList构造方法: public ArrayList();创建一个空的对象集合
ArrayList添加方法: public boolean add(E e);//将指定元素追加到此集合的末尾 public void add(int index, E element);//在此集合的指定位置插入指定的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package ArrayList;import java.util.ArrayList;public class case1 { public static void main (String[] args) { ArrayList<String> array=new ArrayList <String>(); System.out.println(array.add("Hello" )); array.add("world" ); array.add("java" ); array.add(1 ,"good" ); array.add(4 ,"people" ); System.out.println("array : " +array); } }
2、ArrayList的常用方法 public boolean remove(Object o);删除指定元素,返回删除是否成功
public E remove(int index);删除指定索引位置上的元素,并返回删除元素
public E set(int index, E element);修改指定位置处的元素,返回被修改的元素
public E get(int index);返回指定索引处的元素
public int size();返回集合中元素的个数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package ArrayList;import java.util.ArrayList;public class case2 { public static void main (String[] args) { ArrayList<String> array=new ArrayList <String>(); array.add("hello" ); array.add("java" ); array.add("world" ); array.add("hello" ); array.add("world" ); array.add("hello" ); array.add("hello" ); array.add("hello" ); array.add("java" ); array.remove(0 ); array.remove("world" ); array.set(1 ,"begin" ); System.out.println("下标为2的元素为:" +array.get(2 )); System.out.println("集合中元素个数为:" +array.size()); System.out.println("array:" +array); } }
四、面向对象编程 类之间的关系 在软件系统中,类不是孤立存在的,类与类之间存在各种关系。根据类与类之间的耦合度从弱到强排列,UML 中的类图有以下几种关系:依赖关系、关联关系、聚合关系、组合关系、泛化关系和实现关系。其中泛化和实现的耦合度相等,它们是最强的。
1.依赖关系
依赖(Dependency)关系是一种使用关系,它是对象之间耦合度最弱的一种关联方式,是临时性的关联。在代码中,某个类的方法通过局部变量、方法的参数或者对静态方法的调用来访问另一个类(被依赖类)中的某些方法来完成一些职责。
在 UML 类图中,依赖关系使用带箭头的虚线来表示,箭头从使用类指向被依赖的类。
2.关联关系
关联(Association)关系是对象之间的一种引用关系,用于表示一类对象与另一类对象之间的联系,如老师和学生、师傅和徒弟、丈夫和妻子等。关联关系是类与类之间最常用的一种关系,分为一般关联关系、聚合关系和组合关系。我们先介绍一般关联。
关联可以是双向的,也可以是单向的。在 UML 类图中,双向的关联可以用带两个箭头或者没有箭头的实线来表示,单向的关联用带一个箭头的实线来表示,箭头从使用类指向被关联的类。也可以在关联线的两端标注角色名,代表两种不同的角色。
3.聚合关系
聚合(Aggregation)关系是 关联关系的一种,是强关联关系,是整体和部分之间的关系,是 has-a 的关系。
聚合关系也是通过成员对象来实现的,其中成员对象是整体对象的一部分,但是成员对象可以脱离整体对象而独立存在。例如,学校与老师的关系,学校包含老师,但如果学校停办了,老师依然存在。
在 UML 类图中,聚合关系可以用带空心菱形的实线来表示,菱形指向整体。
4.组合关系
组合(Composition)关系也是 关联关系的一种,也表示类之间的整体与部分的关系,但它是一种更强烈的聚合关系,是 cxmtains-a 关系。
在组合关系中,整体对象可以控制部分对象的生命周期,一旦整体对象不存在,部分对象也将不存在,部分对象不能脱离整体对象而存在。例如,头和嘴的关系,没有了头,嘴也就不存在了。
在 UML 类图中,组合关系用带实心菱形的实线来表示,菱形指向整体。
5.泛化(继承)关系
泛化(Generalization)关系是对象之间耦合度最大的一种关系,表示一般与特殊的关系,是父类与子类之间的关系,是一种继承关系,是 is-a 的关系。
在 UML 类图中,泛化关系用带空心三角箭头的实线来表示,箭头从子类指向父类。在代码实现时,使用面向对象的继承机制来实现泛化关系。
6.实现关系
实现(Realization)关系是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。
在 UML 类图中,实现关系使用带空心三角箭头的虚线来表示,箭头从实现类指向接口。
异同分析
在代码层面的体现方式
1.继承 在Java语言中,一个类继承另一个类需要使用关键字extends,关键字extends的使用方法如下:
1 public class child extends parent {}
Java只支持单继承,即一个类只有一个父类,子类在继承父类的方法后,创建子类对象的同时也会调用父类的构造方法,其中会先执行父类的构造方法,再执行子类的构造方法。子类继承父类后,可以调用父类创建好的方法和属性。
继承的好处与弊端:
好处:
弊端:
继承让类与类之间产生了关系,类的耦合性增强了。当父类发生变化时子类实现也不得不跟着变化,削弱了子类的独立性
继承中变量的访问特点
在子类方法中访问一个变量
子类局部范围内找
子类成员范围找
父类成员范围找
如果没有就会报错(不考虑父亲的父亲)
super 关键字
super关键字和this关键字的用法相似
this代表本类对象的引用
super代表父类存储空间的标识(可以理解为父类对象引用)
关键字
访问成员变量
访问构造方法
访问成员方法
this
this.成员变量 访问本类成员变量
this(……) 访问本类构造方法
this.成员方法(……)访问本类成员方法
super
super.成员变量 访问父类成员变量
super(……) 访问父类构造方法
super.成员方法(……)访问父类成员方法
instanceof 关键字
该关键字可以用来判断是否一个类实现了某个接口或者用来判断一个实例化对象是否属于一个类,其返回类型是布尔类型
1 2 3 4 5 6 7 8 9 10 class Quadrangle { }class Square extends Quadrangle { }class Circular { }public class Demo { public static void main (String[] args) { Quadrangle q=new Quadrangle (); Square s=new Square (); System.out.println(q instanceof Square); } }
继承中构造方法的访问特点
子类中所有的构造方法默认都会访问父类中无参的构造方法
子类会继承父类中的数据,可能还会使用父类中的数据。所以,子类初始化前,一定要先完成父类数据的初始化
每一个子类构造方法的第一条语句默认为: super()
如果父类中没有无参构造方法,只有带参构造方法,有两种解决方案:
通过使用super关键字去显式的调用父类的带参构造方法
在父类中提供一个无参构造方法
继承中成员方法的访问特点
通过子类对象访问一个方法
子类成员范围中找
父类范围成员找
如果都没有则会报错(不考虑父亲的父亲)
方法重写:
应用:
当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容
@Override
是一个注解
可以帮助我们检查重写方法的方法声明的正确性
注意事项:
私有方法不能被重写(父类私有成员子类不能继承)
子类方法的访问权限不能更低(public>默认>私有)
Java继承中注意事项:
Java中类只支持单继承,不支持多继承
Java中类支持多层继承
修饰符
1.包的概述与使用
其实就是文件夹,作用是对类进行分类管理
包的定义格式:
package 包名;(多级包.分开)
带包的Java类编译和执行
手动建包:按照以前的格式编译java文件 javac xxx.java
手动创建包 在x盘建立文件夹com然后在com下建立文件夹itheima
把class文件放到包的最里面 把xxx.class文件放到com.itheima这个文件夹下
带包执行 java com.itheima.xxx
自动建包:javac-d .xxx.java java com.itheima.xxx
2.导包
使用不同包下的类时,使用的时候要写类的全路径,写起来太麻烦了,为了简化带包的操作,Java提供了导包的功能
导包的格式:
import 包名;
3.修饰符
修饰符
同一个类中
同一个包中子类无关类
不同包的子类
不同包的无关类
private
√
默认
√
√
protected
√
√
√
public
√
√
√
√
状态修饰符:
final 最终 可以修饰成员方法,成员变量,类
final修饰的特点
修饰方法:表明该方法是最终方法,不能被重写
修饰变量:表明该变量是常量,不能再次被赋值
修饰类:表明该类是最终类,不能被继承
final修饰局部变量
变量是基本数据类型:final修饰指的是基本数据类型的数据值不能发生改变
变量是引用类型:final修饰指的是引用类型的地址值不能改变,但是地址里面的内容是可以改变的
static 静态 可以修饰成员方法和成员变量
static修饰的特点
被类的所有对象共享(这也是判断我们是否使用静态关键字的条件)
可以通过类名调用(也可以通过对象调用)
static访问特点
非静态的成员方法
能访问静态的成员变量
能访问非静态的成员变量
能访问静态的成员方法
能访问非静态的成员方法
静态的成员方法
2.多态 同一个对象,在不同时刻表现出来的不同的形态
举例:
猫 cat= new 猫();
动物 animal =new 猫();
这里猫在不同时刻表现出来了不同的形态,这就是多态。
多态的前提和体现
有继承/实现关系
有方法重写
有父类引用指向子类对象
多态中成员的访问特点
成员变量:编译看左边,执行看左边
成员方法:编译看左边,执行看右边(因为成员方法有重写,而成员变量没有重写)
多态的好处与弊端
好处:提高了程序的扩展性
具体实现:定义方法的时候,使用父类型作为参数,将来使用的时候,使用具体的子类型参与操作
弊端:不能使用子类的特有功能
执行顺序 :先执行父类的静态语句(哪句语句在前先执行)再执行子类的静态语句(哪句语句在前先执行),再执行父类的代码块、成员属性赋值(哪个在前哪个先执行),后执行父类的构造方法,最后执行子类的代码块、成员属性赋值(哪个在前哪个先执行),后执行子类的构造方法。
多态中的转型
3.内部类 1.类名作为形参和返回值
方法的形参是类名,其实需要的是该类的对象
方法的返回值值是类名,其实返回的是该类的对象
2.抽象类名作为形参和返回值
方法的形参是抽象类名,其实需要的是该抽象类的子类对象
方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
3.接口名作为形参和返回值
方法的形参是接口名,其实需要的是该接口的实现类对象
方法的返回值是接口名,其实返回的是该接口的实现类对象
内部类:就是在一个类中定义一个类。
内部类的定义格式:
1 2 3 4 5 public class 类名{ 修饰符 class 类名{ } }
内部类的访问特点:
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
成员内部类不止可以在外部类中使用,在其他类中也可以使用。语法如下:
1 2 外部类 outer =new 外部类(); 外部类.内部类 inter=new outer .new 内部类();
如果在外部类和非静态方法之外实例化内部类对象,需要使用“外部类.内部类”的形式指向该对象的类型。
内部类对象会依赖于外部类对象,除非已经存在一个外部类对象,否则类中不会出现内部类对象。
使用this 关键字获取内部类和外部类之间的引用
如果在外部类中定义的成员变量与内部类的成员变量名称相同,可以使用this关键字
1 2 3 4 5 6 7 8 9 10 11 12 public class TheSameName { private int x=7 ; private class Inter { int x=9 ; public void work () { int x=11 ; x++; this .x++; TheSameName.this .x++; } } }
匿名内部类:
匿名内部类是在创建对象时才会编写类体的一种写法,匿名类的特点是“现用现写 ”,其语法如下:
注意:最后一个大括号之后有分号
匿名类的特点:
匿名类不能写构造方法
匿名类不能定义静态的成员变量
如果匿名类创建的对象没有赋值给任何引用变量,会导致该对象用完一次后就会被Java虚拟机销毁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public abstract class Dog { String Color; public abstract void move () ; public abstract void call () ; } public class Demo { public void main (String[] args) { Dog temp=new Dog (){ public void move () { System.out.println("四腿狂奔" ); } public void call () { System.out.println("嗷呜~" ); } }; temp.Color="灰色" ; temp.move(); temp.call(); } }
说明:匿名内部类编译以后,会产生以“外部类名$序号”为名称的.class文件,序号以1~n排列,分别代表1-n个匿名内部类。
4.Object类 Java中所有类都直接或者间接继承了java.lang.Object类.Object类是比较特殊的类,它是所有类的父类,是Java类中的最高层类。
Object类的常用方法:
方法
说明
getClass()
它会返回对象执行时的Class实例,此外也可以通过此实例调用getName()方法取得类名。getClass().getName();
toString()
将一个对象返回以字符串的形式,它会返回一个String实例。
equals()
“==”比较的是两个对象引用地址是否相等,而equals()比较的是两个对象的实际内容。
toString()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Main { public static void main (String[] args) { Object obj = new Object (); String str1 = obj.toString(); System.out.println(str1); System.out.println(obj); } }
equals()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 import java.util.Objects;public class Student { private String name; private int age; @Override public boolean equals (Object o) { if (this == o) return true ; if (o == null || getClass() != o.getClass()) return false ; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); } }
五、常用API 1.Math类 Math包括执行基本数学运算的方法,如基本指数,对数,平方根和三角函数。
调用形式:
Math.数学方法
也存在一些常用数字常量 如:Math.PI Math.E
1.三角函数方法:
1 2 3 4 5 6 7 8 9 public static double sin (double a) ; public static double cos (double a) ;public static double tan (double a) ; public static double asin (double a) ;public static double acos (double a) ; public static double atan (double a) ; public static double toRadians (double a) ; public static double toDegrees (double a) ;
2.指数函数方法:
1 2 3 4 5 6 public static double exp (double a) ;public static double log (double a) ;public static double log10 (double a) ;public static double sqrt (double a) ;public static double cbrt (double a) ;public static double pow (double a,double b) ;
3.取整函数方法
1 2 3 4 5 public static double ceil (double a) ;public static double floor (double a) ;public static double rint (double a) ;public static int round (double a) ;public static long round (double a) ;
4.取最大值、最小值、绝对值方法
1 2 3 public static double max (double a,double b) ;public static int /long /float /double min (double a,double b) ;public static int /long /float /double abs (double a) ;
2.BigInteger类 BigInteger类的数字范围比Integer类的大得多,BigInteger类支持任意精度的整数,使用BigInteger类进行运算可以准确无误地表示任何大小的整数值并且不会丢失任何信息。语法如下:
1 2 BigInteger twoInstance = new BigInteger ("2" );
BigInteger类的常用运算方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public BigInteger add (BigInteger val) ;public BigInteger subtract (BigInteger val) ;public BigInteger multiply (BigInteger val) ;public BigInteger divide (BigInteger val) ;public BigInteger remainder (BigInteger val) ;public BigInteger[] divideAndRemainder(BigInteger val);public BigInteger pow (int exponent) ;public BigInteger negate () ;public BigInteger shiftLeft (int n) ;public BigInteger shiftRight (int n) ;public BigInteger and (BigInteger val) ;public BigInteger or (BigInteger val) ;public int compareTo (BigInteger val) ;public boolean equals (Object x) ;public BigInteger max (BigIntegr val) ;public BigInteger min (BigInteger val) ;
样例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.math.BigInteger;public class Demo2 { public static void main (String[] args) { BigInteger x=new BigInteger ("222222222" ); BigInteger y=new BigInteger ("111111111" ); BigInteger z=x.add(y); BigInteger c=x.subtract(y); BigInteger v=x.multiply(y); BigInteger u=x.divide(y); BigInteger r=x.remainder(y); BigInteger Max=x.max(y); BigInteger Min=x.min(y); BigInteger yu=x.and(y); BigInteger huo=x.or(y); BigInteger oppo=x.negate(); BigInteger exp=x.pow(2 ); int ans=x.compareTo(y); BigInteger left=x.shiftLeft(1 ); BigInteger right=x.shiftRight(1 ); BigInteger []arr=x.divideAndRemainder(y); boolean flag=x.equals(12 ); System.out.println("加法运算后的结果:" +z); System.out.println("减法运算后的结果:" +c); System.out.println("乘法运算后的结果:" +v); System.out.println("除法运算后的结果:" +u); System.out.println("取余运算后的结果:" +r); System.out.println("两者中的最大值为:" +Max); System.out.println("两者中的最小值为:" +Min); System.out.println("与操作后的结果:" +yu); System.out.println("或操作后的结果:" +huo); System.out.println("相反数为:" +oppo); System.out.println("参数的2次方结果为:" +exp); System.out.println("做比较操作后的结果为:" +ans); System.out.println("做左移1位后的结果:" +left); System.out.println("做右移1位后的结果:" +right); System.out.println("商:" +arr[0 ]+" 余数:" +arr[1 ]); System.out.println("判断参数与12是否相等:" +flag); } }
3.System类 System类是JDK提供的系统类,该类是用final 修饰的,所以不允许继承,System类提供了很多系统层面的操作方法,并且这些方法全部都是静态的。以下为System类常用方法:
方法
功能描述
currentTimeMillis()
返回以毫秒为单位的当前时间
exit(int status)
通过启动虚拟机的关闭序列,终止当前正在运行的Java虚拟机,此方法从不正常返回,可以将变量作为一个状态码,根据惯例,非零的状态码表示非正常终止;0表示正常终止
Mapgetenv()
返回一个不能修改的当前系统环境的字符串映射视图
getenv(String name)
获取指定的环境变量值
getProperties()
确定当前的系统属性
getProperty(String key)
获取用指定键描述的系统属性
setIn(InputStream in)
重新分配“标准输入流”
System类提供了标准输入、标准输出和错误输出流,即System类提供了三个静态对象:in、out、err.在控制台输出字符串,有两种方法:
1 System.out.print("Hello" );
1 System.out.println("书籍是人类进步的阶梯" );
注意事项:
System.out.println(“\n”); //会打印两个空行
System.out.print(); //没有参数会报错
计时
利用System.currentTimeMillis()方法可以用来记录程序的运行时间
1 2 3 4 5 6 7 8 9 10 11 public class SystemTimeDemo { public static void main (String[] args) { long start=System.currentTimeMillis(); String str=null ; for (int i=0 ;i<10000 ;i++){ str+=i; } long end=System.currentTimeMillis(); System.out.println("循环用时为:" +(end-start)+"毫秒" ); } }
4.Arrays类 Array类包含于用于操作数组的各种方法
方法名
说明
public static String toString(int[] a)
返回指定数组的内容的字符串表达形式
public static void sort(int[] a)
按照数字顺序排列指定的数组
1 2 3 4 5 6 7 8 9 10 11 import java.util.Arrays;public class Main { public static void main (String[] args) { int [] arr={20 ,69 ,80 ,57 ,13 }; System.out.println("排序前:" +Arrays.toString(arr)); Arrays.sort(arr); System.out.println("排序后:" +Arrays.toString(arr)); } }
工具类的设计思想:
构造方法用private修饰
成员用public static修饰
5.基本类型包装类 将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据
常用的操作之一:用于基本数据类型和字符串之间的转换
基本数据类型
包装类
byte
Byte
short
Short
int
Integer
long
Long
float
Float
double
Double
char
Character
boolean
Boolean
Integer类的概述和使用
Integer:包装一个对象中的原始类型int的值
方法名
说明
public Integer(int value)
根据int值创建Integer对象(过时)
public Integer(String s)
根据String值创建Integer对象(过时)
public static Integer valueOf(int i)
返回指定的int值的Integer实例
public static Integer valueOf(String s)
返回一个保存指定值的Interger对象String
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Main { public static void main (String[] args) { Integer i1=new Integer (100 ); System.out.println(i1); Integer i2=new Integer ("100" ); System.out.println(i2); Integer i3=Integer.valueOf(100 ); System.out.println(i3); Integer i4=Integer.valueOf("100" ); System.out.println(i4); } }
int和String的相互转换
1.int →String类型
public static String valueOf(int i):返回int类型参数的字符串表示形式,该方法是String类中的方法。
2.String →int类型
public static int parseInt(String s);将字符串解析成int类型,该方法是Integer类中的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class Main { public static void main (String[] args) { int number=100 ; String s="" +number; System.out.println(s); String s2=String.valueOf(number); System.out.println(s2); System.out.println("----------------" ); String str="1000" ; Integer temp=Integer.valueOf(str); int x=temp.intValue(); System.out.println(x); int y=Integer.parseInt(str); System.out.println(y); } }
6.日期时间类 1.Date类 Date类用于表示日期和时间,使用该类表示时间需要使用其构造方法来创建对象,其构造方法以及说明表如下。
构造方法
方法说明
Date()
分配Date对象并初始化对象,以表示分配它的时间(精确到毫秒)
Date(long date)
分配Date对象并初始化此对象,以表示自标准基准时间(即1970年1月1日00:00:00GMT)起经过指定毫秒数date后的时间
1 2 long timeMillis=System.currentTimeMillis(); Date date = new Date (timeMillis);
创建Date对象使用的是long型整数,而不是double型,这主要是因为double类型可能会损失精度。
Date类的常用方法以及说明
方法
说明
after(Date when)
测试当前日期是否在指定日期之后
before(Date when)
测试当前日期是否在指定日期之前
getTime()
获取自1970年1月1日00:00:00GMT开始到现在所经过的毫秒数
setTime(long time)
设置当前Date对象所表示的日期时间值,该值用以1970年1月1日00:00:00GMT以后time毫秒的时间点
案例1:
获取当前的日期和时间
1 2 3 4 5 6 7 8 9 10 package APIDemp;import java.util.Date;public class DateDmo { public static void main (String[] args) { Date date=new Date (); long value=date.getTime(); System.out.println("日期: " +date); System.out.println("到现在所经历的毫秒数:" +value); } }
日期时间格式化
DateFormat类是日期时间格式化子类的抽象类,可以按照指定的格式对日期或时间进行格式化。DateFormat类提供了很多类方法,以获得基于默认或给定语言环境和多种格式化风格的默认日期时间Formatter,格式化主要包括四种风格:
SHORT:完全为数字,如12.13.52或3:30pm
MEDIUM:较长,如Jan 12, 1952
LONG:更长,如January 12,1953或3:39:32pm
FULL:完全指定,如Tuesday、April 12、1952AD或3:30:34pm PST
另外,使用DateFormat类还可以自定义日期时间的格式。要格式化一个当前语言环境下的日期,首先要创建一个DateFormat类的一个对象,由于它是抽象类,因此可以使用getDateInstance()进行创建,语法如下:
1 DateFormat df = DateFormat.getDateLnstance();
使用getDateInstance()方法获取的是所在国家或地区的标准日期格式,而使用getTimeInstance()获取的是当前所在国家或地区的时间格式,而使用getDateTimeInstance()获取的是当前国家或者地区的日期时间格式。
DateFormat类的常用方法及其说明
方法
说明
format(Date date)
将一个Date对象实例格式化为日期/时间字符串
getCalendar()
获取与此日期时间/时间格式器关联的日历
getDateInstance()
获取日期格式器,该格式器具有默认语言环境的默认格式化风格
getTimeInstance()
获取时间格式器,该格式器具有默认语言环境的默认格式化风格
getDateTimeInstance()
获取日期/时间格式器,该格式器具有默认语言环境的默认格式化风格
getInstance()
获取为日期/时间使用SHORT风格的默认日期/时间格式器
parse(String source)
将字符串解析成一个日期,并返回这个日期的Date对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package APIDemp;import java.text.DateFormat;import java.util.Date;public class DateDmo { public static void main (String[] args) { DateFormat df=DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG); DateFormat df2=DateFormat.getInstance(); Date date=new Date (); System.out.println(df.format(date)); System.out.println(df.format(new Date ())); System.out.println(df2.format(new Date ())); } }
由于DateFormat类是一个抽象类,不能new创建实例对象。因此,出来使用getXXXinstance()方法创建其对象,还可以使用其子类,如SimpleDateFormat类,该类是一个以与语言环境相关的方式来格式化和分析日期的具体类,它允许进行格式化(日期→文本)、分析(文本→日期)和规范化。
SimpleDateFormat的格式化字符
字母
日期或时间元素
类型
示例
G
Era标示符
Text
AD
y
年
Year
1996
M
年中的月份
Month
July;Jul;07
w
年中的天数
Number
27
W
月份中的天数
Number
2
D
年中的天数
Number
179
d
月份中的天数
Number
10
F
月份中的星期
Number
2
E
星期中的天数
Text
Tuesday;Tue
t
Am/pm的标记
Text
PM
H
一天中的小时数(0~23)
Number
0
h
am/pm中的小时数(1~12)
Number
12
k
一天中的小时数(1~24)
Number
24
K
am/pm中的小时数(0~11)
Number
0
m
小时中的分钟数
Number
30
s
分钟中的秒数
Number
55
S
毫秒数
Number
978
z
时区
General time zone
PST
Z
时区
RFC 822 time zone
-800
常用时间格式
日期时间
对于的格式
2021/10/25
yyyy/MM/dd
2021.10.25
yyyy.MM.dd
2021-09-14 13:20:43
yyyy-MM-dd HH:mm:ss
2021年10月21日 10时21分05秒 星期日
yyyy年MM月dd日 HH时mm分ss秒 EEEE
下午3时
ah时
今年已经过去了297天
今年已经过去了D天
案例2:
以中文形式打印当前的日期和时间
1 2 3 4 5 6 7 8 9 10 11 12 package APIDemp;import java.text.DateFormat;import java.util.Date;import java.text.SimpleDateFormat;public class DateDmo { public static void main (String[] args) { DateFormat df=new SimpleDateFormat ("yyyy年MM月dd日 HH时mm分ss秒 EEEE" ); System.out.print("各位观众大家好,现在是:" ); System.out.print(df.format(new Date ())); System.out.println(", 欢迎大家收看新闻" ); } }
7.集合类 集合可以看成一个容器,Java中提供了不同的集合类,这些类有不同的存储对象,同时提供了相应的方法,以方便用户对集合进行遍历、添加、删除和查找指定的对象。集合类与数组的不同之处是:数组长度是固定的,集合的长度是可变的;数组常用来存储基本类型的数据,集合用来存放对象的引用。常用的集合有List集合、Set集合和Map集合,其中List集合与Set集合继承了Collection接口,各接口还提供了不同的实现类。
1.Collection接口 Collection接口是层次结构中的根接口,构成Collection的单位称为元素。Collection接口通常不能直接使用,但该接口提供了添加元素、删除元素、管理数据的方法。由于List接口与Set接口都继承了Collection接口,因此这些方法对List集合与Set集合是通用的。Collection接口的常用方法如下:
方法
功能描述
add(E e)
将指定对象添加到集合中
remove(Object o)
将指定的对象从该集合中移除
isEmpty()
返回boolean值,用于判断当前集合是否为空
iterator()
返回在此Collection的元素上进行迭代的迭代器,用于遍历集合中的对象
size()
返回int型值,获取该集合中元素的个数
通常遍历集合,都是通过迭代器来实现
案例:
向购物车添加商品
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package APIDemp;import java.util.*;public class CollectionDemo { public static void main (String[] args) { Collection<String>list=new ArrayList <>(); list.add("《Java从入门到精通》" ); list.add("《零基础学Java》" ); list.add("《Java编程思想》" ); Iterator<String> it=list.iterator(); while (it.hasNext()){ String str=(String)it.next(); System.out.println(str); } } }
2.List集合 1.List接口
List接口继承了Collection接口,因此包含Collection接口中的所有方法。此外List接口还定义了两个重要的方法:
方法
说明
get(int index)
获得指定索引位置的元素
set(int index,Object obj)
将集合中指定索引位置的对象修改为指定的对象
2.List接口的实现类
ArrayList类实现了可变的数组,允许保存所有元素,包括null,并可以根据索引位置对集合进行快速的随机访问。缺点是向指定的索引位置插入对象或者删除对象的速度较慢。
LinkedList类采用链表的结构保存对象。这种结构的优点是便于向集合中插入和删除元素。需要向集合中插入、删除对象时,使用LinkedList类实现的List集合的效率较高;但对于随机访问集合中的元素,使用LinkedList类实现List集合的效率较低。
1 2 List<E> list = new ArrayList <>(); List<E> list2 = new LinkedList <>();
注意:与数组相同,集合的索引也是从0开始的。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package APIDemp;import java.util.*;public class ListDemo { public static void main (String[] args) { List<String> list = new ArrayList <>(); list.add("a" ); list.add("b" ); list.add("c" ); list.set(0 ,"d" ); int i=(int )(Math.random()*list.size()); System.out.println("随机获取集合中的元素:" +list.get(i)); list.remove(i); System.out.println("集合中剩下的元素分别是:" ); for (int j=0 ;j<list.size();j++){ System.out.println(list.get(j)); } } }
3.Set集合 Set集合中的对象不按特定的方式排序,只是简单地把对象加入到集合中,但Set集合中不能包含重复对象。Set集合由Set接口和Set接口的实现类组成。因此包含Collection接口的所有方法。
Set接口常用的实现类有HashSet类和TreeSet类,简述如下:
HashSet类实现Set接口,由哈希表(实际上是一个HashMap实例)支持。它不保证Set集合的迭代顺序,特别是它不保证该顺序永恒不变。此类允许使用元素null。
TreeSet类不仅实现了Set接口,还实现了java.util.SortSet接口,因此TreeSet类实现的Set集合在遍历集合按照自然顺序递增排序,也可以按照指定比较器递增排序,即可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序。
TreeSet类增加的方法
方法名称
功能描述
first()
返回此Set集合中当前第一个(最低)元素
last()
返回此Set集合中当前最后一个(最高)元素
comparator()
返回对此Set集合中的元素是进行排序的比较器。如果该集合采用的是自然顺序排序,则返回null
headSet(E toElenment)
返回一个新的Set集合,新集合是toElement对象(不包含)之前的所有对象
subSet(E fromElement,E fromElement)
返回一个新的Set集合,新集合是fromElement对象(包含)与fromElement对象(不包含)之间的所有对象
tailSet(E fromElement)
返回一个新的Set集合,新集合包含fromElement对象(包含)之后的所有对象
案例:
使用TreeSet类完成自然(升序)排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package APIDemp;import java.util.Iterator;import java.util.Set;import java.util.TreeSet;import java.util.Scanner;public class SetDemo { public static void main (String[] args) { TreeSet<Integer> temp=new TreeSet <>(); temp.add(12 ); temp.add(21 ); temp.add(-3 ); temp.add(6 ); temp.add(85 ); System.out.println("集合中的第一个元素:" +temp.first()); System.out.println("集合中的最后一个元素:" +temp.last()); Iterator<Integer> it=temp.iterator(); System.out.print("temp中的集合元素为:" ); while (it.hasNext()){ System.out.print(it.next()+" " ); } System.out.println(); Set<Integer> temp2=temp.headSet(12 ); Iterator<Integer> it2=temp2.iterator(); while (it2.hasNext()){ System.out.print("temp2中的集合元素为:" ); while (it2.hasNext()){ System.out.print(it2.next()+" " ); } } System.out.println(); Set<Integer> temp3=temp.tailSet(12 ); Iterator<Integer> it3=temp3.iterator(); while (it3.hasNext()){ System.out.print("temp3中的集合元素为:" ); while (it3.hasNext()){ System.out.print(it3.next()+" " ); } } System.out.println(); Set<Integer> temp4=temp.subSet(6 ,21 ); Iterator<Integer> it4=temp4.iterator(); while (it4.hasNext()){ System.out.print("temp4中的集合元素为:" ); while (it4.hasNext()){ System.out.print(it4.next()+" " ); } } System.out.println(); } }
4.Map集合 Map集合没有继承Collection接口,其提供的是key到value的映射。Map集合中不能包含相同的Key,每个key只能映射一个value.key还决定了存储对象在映射中的存储位置,但不是由key对象本身决定的,而是通过一种”散列技术”进行处理,产生一个散列码的整数值。散列码通常用作一个偏移量,该偏移量对应分配给映射的内存区域的起始位置,从而确定存储对象在映射中的存储位置。Map集合包含Map接口和Map接口的所有实现类。
1.Map接口
Map接口提供了将key映射到值的对象。一个映射不能包含重复的key,每个key最多只能映射到一个值。除集合的常用方法外,Map接口还提供了下图所示方法:
Map常用方法
方法
功能描述
put(K key,V value)
向集合中添加所指定的key与value的映射关系
containsKey(Object key)
如果此映射中包含指定key的映射关系,则返回true
contaninsValue(Object value)
如果此映射将一个或者多个key映射到指定值,则返回true
get(Object key)
如果存在指定的key对象,则返回该对象的值,否则返回null
keySet()
返回该集合中的所有key对象形成的Set集合
values()
返回该集合中的所有值对象形成的Collectin集合
remove(Object key)
从映射中删除与Key相关的映射
putAll(Map t)
将来自特定映像的所有元素添加给该映像
clear()
删除所有映射
2.Map接口的实现类
SortedMap接口 用来保持键的有序顺序
方法
功能描述
Comparator comparator()
返回对关键字进行排序时使用的比较器,如果使用Comparable接口的compareTo() 方法进行关键字比较,则返回null
Object firstKey()
返回映射中第一个(最低)关键字
Object lastKey()
返回映射中最后一个(最高)关键字
SortedMap subMap(Object fromKey,Object toKey)
返回从fromKey(包括)到toKey(不包括)范围内的元素的SortedMap视图(子集)
SortedMap headMap(Object toKey)
返回SortedMap的第一个视图,其内各元素的key都小于toKey
SortedMap tailMap(Object fromKey)
返回SortedMap中的最后一个视图,里面元素的key都大于或者等于fromKey
HashMap是基于哈希表的Map接口实现,此实现提供所有可选的映射操作,并允许使用null值和null键,但必须保证键的唯一性。HashMap类通过哈希表对其内部的映射关系进行快速查找。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
TreeMap类不仅实现了Map接口,还实现了java.util.SortMap接口,因此集合中的映射关系具有一定的顺序。但在添加、删除、定位映射关系时,TreeMap类比HashMap类性能较差。由于TreeMap类实现的Map集合中的映射关系是根据键对象按照一定的顺序排列的,因此不允许键对象是null。
六、泛型 泛型 :是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型 它的本质是参数化类型 ,也就是说所操作的数据类型被指定为一个参数,顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型 ,这种参数类型可以用在类、方法和接口中,分别称为泛型类、泛型方法、泛型接口
泛型定义格式:
<类型> : 指定一种类型的格式,这里的类型可以看成是形参
<类型1,类型2>:指定多种类型的格式,多种类型用逗号隔开。这里的类型可以看成是形参
将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型
泛型的好处:
把运行时期的问题提前到了编译期间
避免了强制类型转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package Generic;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import java.util.Objects;public class GenericDemo { public static void main (String[] args) { Collection<String> c = new ArrayList <String>(); c.add("hello" ); c.add("world" ); c.add("java" ); Iterator<String> it = c.iterator(); while (it.hasNext()){ String s = it.next(); System.out.println(s); } } }
泛型类
泛型类的定义格式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package Generic;public class Generic <T> { private T t; public T getT () { return t; } public void setT (T t) { this .t = t; } public static void main (String[] args) { Generic<String> g1 = new Generic <String>(); g1.setT("李清霞" ); System.out.println(g1.getT()); Generic<Integer> g2 = new Generic <Integer>(); g2.setT(30 ); System.out.println(g2.getT()); Generic<Boolean> g3 = new Generic <Boolean>(); g3.setT(true ); System.out.println(g3.getT()); } }
泛型类中的泛型成员不能直接实例化。 它们的实例化必须通过相关方法的参数来传递给他们。
1 2 3 4 5 6 7 8 9 10 public class Main <T>{ private T[] array; public void setArray (T[] tt) { array = tt; } public T[] getArray() { return array; } }
同一个泛型类,如果实例化时给予的实际具体类型不一样,那么这些实例类型是不兼容的,不能相互赋值。
泛型方法
泛型方法的定义格式:
格式:修饰符 <类型> 返回值类型 方法名 (类型 变量名){ }
范例:public void show( T t) { }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package Generic;public class Generic { public <T> void show (T t) { System.out.println(t); } public static void main (String[] args) { Generic g = new Generic (); g.show("李清霞" ); g.show(100 ); g.show(true ); g.show(100.100 ); } }
泛型接口
泛型接口的定义格式:
格式:修饰符 interface 接口名 <类型> { }
范例:public interface Generic { }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package Generic;public interface Generic <T>{ void show (T t) ; } package Generic;public class Genericlmpl <T> implements Generic <T> { @Override public void show (T t) { System.out.println(t); } } package Generic;class GenericDemo { public static void main (String[] args) { Generic<String> g1 = new Genericlmpl <String>(); g1.show("李清霞" ); Generic<Integer> g2 = new Genericlmpl <Integer>(); g2.show(100 ); } }
类型通配符
为了表示各种泛型List的父类,可以使用通配符
类型通配符:<?>
List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
如果说我们不希望任何List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
类型通配符上限:<? extends 类型>
List<? extends Number>:它表示的类型是Number或者其子类型
除了可以指定类型通配符的上限,也可以指定类型通配符的下限
类型通配符下限:<? super 类型>
List<? super Number>:它表示的类型是Number或者其父类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package Generic;import java.util.ArrayList;import java.util.List;import java.util.Objects;class GenericDemo { public static void main (String[] args) { List<?> list1 = new ArrayList <Object>(); List<?> list2 = new ArrayList <Number>(); List<?> list3 = new ArrayList <Integer>(); System.out.println("-------" ); List<? extends Number > list4 = new ArrayList <Number>(); List<? extends Number > list5 = new ArrayList <Integer>(); System.out.println("--------" ); List<? super Integer> list6 = new ArrayList <Number>(); List<? super Number> list7 = new ArrayList <Number>(); } }
可变参数
可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的
格式:修饰符 返回值类型 方法名(数据类型… 变量名){ }
范例:public static int sum(int… a){ }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package Generic;public class ArgsDemo1 { public static void main (String[] args) { System.out.println(sum(20 ,20 )); System.out.println(sum(20 ,20 ,30 )); System.out.println(sum(20 ,20 ,30 ,40 )); System.out.println(sum(20 ,20 ,30 ,40 ,50 )); System.out.println(sum(20 ,20 ,30 ,40 ,50 ,60 )); } public static int sum (int ... a) { int sum = 0 ; for (int i:a){ sum += i; } return sum; } }
可变参数注意事项:
这里的变量其实是一个数组
如果一个方法有多个参数,包含可变参数,可变参数要放最后
1 public static int sum (int b,int ... a) { }
可变参数的使用
Arrays工具类中有一个静态方法:
public static List asList(T… a); 返回由指定数组支持的固定大小的列表
返回的集合不能做增删操作,可以做修改操作
List接口中有一个静态方法:
public static List of(E… elements); 返回包含任意数量元素的不可变列表
返回的集合不能做增删改操作
Set接口中有一个静态方法:
public static Set of(E… elements); 返回一个包含任意数量元素的不可变集合
在给元素时,不能给重复的元素
返回的集合不能做增删操作,没有修改的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package Generic;import java.util.Arrays;import java.util.List;import java.util.Set;public class ArgsDemo2 { public static void main (String[] args) { List<String> list = Arrays.asList("hello" , "world" , "java" ); list.set(1 , "你好" ); System.out.println(list); List<String> list2 = List.of("hello" , "world" , "java" , "world" ); System.out.println(list2); Set<String> set = Set.of("hello" ,"world" ,"java" ); System.out.println(set); } }
七、异常 异常就是代表程序出现的问题。其父类是 Throwable。其下两个子类,Error 和 Exception。Error 代表的是系统级别的错误(严重问题),是SUN公司自己用的。而 Exception 代表程序可能出现的问题。Exception 分为 RuntimeException 和其他异常。其中,RuntimeException 是运行时异常,编译阶段不会被检测出来,编译阶段 Java 不会执行代码,只会检查语法是否错误,或者做一些性能优化 。编译时异常更多是提醒程序员检查本地信息,运行时异常是代码逻辑出错而导致程序出现的问题。
idea 当中使用 Ctrl + Alt + T 进行 try catch 包裹。
Error:代表的系统级别错误(属于严重问题)
Exception:异常,代表程序可能出现的问题,通常用Exception以及它的子类来封装程序出现的问题。
运行时异常:RuntimeException及其子类,编译阶段不会出现异常提醒。运行时出现的异常(如:数组索引越界异常)
编译时异常:除了Exception及其子类,其他都是编译时异常。编译阶段就会出现异常提醒的。(如:日期解析异常)
编译阶段:java不会运行代码,只会检查语法错误,或者做一些性能的优化
1 2 3 4 5 6 Java文件 ⬇ Javac命令 字节码文件 ⬇ Java命令 运行结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package myException;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class ExceptionDemo1 { public static void main (String[] args) throws ParseException { String time = "2023年12月18日" ; SimpleDateFormat sdf = new SimpleDateFormat ("yyyy年MM月dd日" ); Date date = sdf.parse(time); System.out.println(date); int [] arr = {1 ,2 ,3 ,4 ,5 }; System.out.println(arr[5 ]); } }
异常的作用
是用来查询bug的关键参考信息。
异常可以作为方法内部的一种特殊返回值,以便通知调用者底层的执行情况(看异常的发生位置可以从下往上读) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Student { int age; String name; void setAge (int age) { if (age < 18 || age > 40 ) { throw new RuntimeException (); } this .age = age; } } public class Main { public static void main (String[] args) { Student s1 = new Student (); s1.setAge(19 ); s1.setAge(17 ); } }
异常的处理方式 异常的常见处理方式有:
JVM默认处理。
捕获异常。
抛出异常。
其中,抛出 主要是告诉调用者出错 了。而捕获 主要是为了不让程序停止 。
JVM默认处理 把异常的名称,异常原因以及异常出现的位置等信息用红色字体打印在控制台上。并且此时的程序停止,代码不再执行。
捕获异常 目的是让异常出现的时候,让程序继续执行 。基本语法为:
1 2 3 4 5 try { 可能出现异常的代码; } catch (异常类名 变量名){ 异常的处理代码; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Main { public static void main (String[] args) { int [] arr = {1 , 2 , 3 , 4 }; try { System.out.println(arr[10 ]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("索引越界了" ); } System.out.println("看看我执行了吗" ); } }
关于捕获异常的四个注意点:
如果 try 中没有遇到问题 ,会执行 try 当中的所有代码,不会执行 catch 的代码。也就是说,catch 当中的代码只有出现了了异常才会执行。
如果 try 中遇到多个问题 ,如果第一个问题能够被顺利捕获,则接下来 try 中代码便不会执行 。最佳解决方案是写多个 catch 捕获多个问题(一行一个 catch或者一行中利用 |
连接),并且,如果异常之间有父子类关系的话,父类一定要写在下面 。
如果 try 中遇到的问题没有被捕获 ,则使用 JVM 默认处理异常的方式进行处理。
如果 try 中遇到了问题 ,try 下面的其他代码便不会执行 了,直接跳到 catch,但如果没有 catch 与之匹配,则按照 JVM 默认处理异常的方式进行处理。
赋值运算符(=)的关联性是从右到左, 因此若一条赋值语句的左右两边都出现异常,则会先抛出等号右边的异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package exceptions2;public class ExDemo3 { public static void method1 () { int [] arrayOfNumbers = new int [10 ]; try { arrayOfNumbers[10 ] = 11 ; } catch (NumberFormatException e1) { System.out.println("NumberFormatException => " + e1.getMessage()); } catch (IndexOutOfBoundsException e2) { System.out.println("IndexOutOfBoundsException => " + e2.getMessage()); } } public static void method2 () { try { int array[] = new int [10 ]; array[10 ] = 30 / 0 ; } catch (ArithmeticException e) { System.out.println(e.getMessage()); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.getMessage()); } } public static void main (String[] args) { method2(); } }
抛出异常
throws :写在方法定义处,表示声明一个异常。告诉调用者,使用本方法可能会有哪些异常。如果是编译时异常,必须要写,如果是运行时异常,可以不写。
throw :写在方法内,结束方法。手动抛出异常对象,交给调用者。方法中下面的代码不在执行了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class Main { public static void main (String[] args) { int [] arr = null ; int sum = 0 ; try { sum = getSum(arr); } catch (NullPointerException e) { System.out.println("空指针异常" ); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("索引异常" ); } System.out.println(sum); } public static int getSum (int [] number) throws NullPointerException, ArrayIndexOutOfBoundsException { if (number == null ) { throw new NullPointerException (); } if (number.length == 0 ) { throw new ArrayIndexOutOfBoundsException (); } int result = 0 ; for (int index : number) { result += index; } return result; } }
异常中的常见方法
方法名称
说明
public String getMessage()
返回此 throwable 的详细消息字符串
public String toString()
返回此可抛出的简短描述
public void printStackTrace()
把异常的错误信息输出在控制台,但不停止虚拟机的运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Main { public static void main (String[] args) { int [] arr = {1 , 2 , 3 , 4 }; try { System.out.println(arr[10 ]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println(e.getMessage()); System.out.println(e.toString()); e.printStackTrace(); } System.out.println("看看我执行了吗" ); } }
自定义异常 自定义异常的目的是为了让报错信息更加见名知意。步骤如下:
定义异常类(编译时异常继承 Exception,运行时异常继承 RuntimeException)。
写继承关系。
空参构造。
带参构造。
如果try catch 语句中有返回值,并且语句中含有finally关键字,则return 后仍然会执行finally中的语句,即finally关键字包围的语句一定执行。 return的如果是基本数据类型,则在finally块中不可以修改已返回的数据,如果是引用类型,则可以改变。
八、I/O流 8.1File File类概述和构造方法
File:它是文件和目录路径名的抽象表示
文件和目录是可以通过File封装成对象的
对于File而言,其封装的并不是一个真正存在的文件,仅仅只是一个路径名。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转化为具体存在的
方法名
说明
File(String pathname)
通过将给定的路径名字符串转化为抽象路径名来创建新的File实例
File(String parent,String child)
从父路径名字符串和子路径名字符串创建新的File实例
File(File parent,String child)
从父抽象路径名和子路径名字符串创建新的File实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package File;import java.io.File;public class FileDemo1 { public static void main (String[] args) { File f1 = new File ("D:\\IDEA\\java.txt" ); System.out.println(f1); File f2 = new File ("D:\\IDEA" ,"java.txt" ); System.out.println(f2); File f3 = new File ("D:\\IDEA" ); File f4 = new File (f3,"java.txt" ); System.out.println(f4); } }
File类创建功能
方法名
说明
public boolean createNewFile()
当具有该名称的文件不存在时,创建一个由该抽象路径命名的新空文件
public boolean mkdir()
创建由此抽象路径命名的目录
public boolean mkdirs()
创建由此抽象路径命名的目录,包括任何必需但不存在的父目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package File;import java.io.File;import java.io.IOException;public class FileDemo2 { public static void main (String[] args) throws IOException { File f1 = new File ("D:\\IDEA\\java.txt" ); System.out.println(f1.createNewFile()); System.out.println("--------" ); File f2 = new File ("D:\\IDEA\\JavaSE" ); System.out.println(f2.mkdir()); System.out.println("--------" ); File f3 = new File ("D:\\IDEA\\JavaWEB\\HTML" ); System.out.println(f3.mkdirs()); System.out.println("--------" ); File f4 = new File ("D:\\IDEA\\javase.txt" ); System.out.println(f4.createNewFile()); } }
File类判断和获取功能
方法名
说明
public boolean isDirectory()
测试此抽象路径名表示的File是否为目录
public boolean isFile()
测试此抽象路径名表示的File是否为文件
pblic boolean exists()
测试此抽象路径名表示的File是否存在
public String getAbsolutePath()
返回此抽象路径名的绝对路径名字符串
public String getPath()
将此抽象路径名转换为路径字符串
public String getName()
返回此抽象路径名表示的文件或者目录的名称
public String[] list()
返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
public File[] listFiles()
返回此抽象路径名表示的目录中的文件和目录中的File对象数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package File;import java.io.File;public class FileDemo4 { public static void main (String[] args) { File f1 = new File ("protect\\java.txt" ); System.out.println(f1.isDirectory()); System.out.println(f1.isFile()); System.out.println(f1.exists()); System.out.println(f1.getAbsolutePath()); System.out.println(f1.getPath()); System.out.println(f1.getName()); System.out.println("--------" ); File f2 = new File ("D:\\IDEA" ); String[] strArray = f2.list(); for (String str:strArray){ System.out.println(str); } System.out.println("--------" ); File [] fileArray = f2.listFiles(); for (File file : fileArray){ if (file.isFile()){ System.out.println(file.getName()); } } } }
File删除功能
方法名
说明
public boolean delete()
删除由此抽象路径名表示的文件或目录
绝对路径和相对路径的区别:
绝对路径:完整的路径名 ,不需要任何其他信息就可以定位它所表示的文件。例如:D:\IDEA\java.txt
相对路径:必须使用取自其他路径名的信息进行解释。例如:IDEA\java.txt
删除目录时的注意事项:
如果一个目录中有内容(目录、文件),不能直接删除 ,必须先删除目录中的内容,最后才能删除目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 package File;import java.io.File;import java.io.IOException;public class FileDemo3 { public static void main (String[] args) throws IOException { File f1 = new File ("java.txt" ); System.out.println(f1.createNewFile()); System.out.println(f1.delete()); System.out.println("--------" ); File f2 = new File ("D:\\IDEA\\itcast" ); System.out.println(f2.mkdir()); System.out.println(f2.delete()); System.out.println("--------" ); File f3 = new File ("D:\\IDEA\\itcast" ); System.out.println(f3.mkdir()); File f4 = new File ("D:\\IDEA\\itcast\\java.txt" ); System.out.println(f4.createNewFile()); System.out.println("--------" ); System.out.println(f4.delete()); System.out.println(f3.delete()); } }
案例:遍历目录
需求:给定一个路径(D:\IDEA),请通过递归完成遍历该目录下的所有内容,并把所有内容的绝对路径输出在控制台
九、反射 反射允许对封装类的字段、方法和构造函数的信息进行编程访问
IDEA中crtl+p能够弹出括号内需要的参数类型
字段(成员变量):获取修饰符、名字、类型,赋值/获取值
构造方法:获取修饰符、名字、形参,创建对象
成员方法:获取修饰符、名字、形参、返回值,抛出的异常、获取注解、允许方法
9.1获取class对象 获取class对象的三种方式:
Class.forName(“全类名”);
类名.class
对象.getClass();
源代码阶段 :Java文件 A.java → class文件 A.class 第一种方式
加载阶段 :将A.class放到内存中 第二种方式
运行阶段 :A a = new ( );第三种方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package Reflect;public class MyReflectDemo1 { public static void main (String[] args) throws ClassNotFoundException { Class clazz = Class.forName("Reflect.Student" ); System.out.println(clazz); Class clazz2 = Student.class; System.out.println(clazz2); Student s = new Student (); Class clazz3 = s.getClass(); System.out.println(clazz3); System.out.println(clazz == clazz2); System.out.println(clazz == clazz3); } }
Java中万物皆对象,Java中有Class 用来描述字节码文件,这个类的对象就是字节码文件的对象,有Constructor 来描述构造方法,这个类的对象就表示这个构造方法的对象,Field 用来描述字段(成员变量),这个类的对象就是成员变量的对象,Method 用来描述成员方法,这个类的对象就是成员方法的对象
9.2利用反射获取构造方法 Class类中用于获取构造方法的方法
Constructor<?>[] getConstructors();返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors(); 返回所有构造方法对象的数组
Constructor getConstructor(Class<?>…parameterTypes);返回单个公共构造方法对象
Constructor getDeclaredConstructor(Class<?>…parameterTypes);返回单个构造方法对象
Constructor类中用于创建对象的方法
T newInstance(Object… initargs);根据指定的构造方法创建对象
setAccessible(boolean flag);设置为true,表示取消访问检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 package Reflect;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Parameter;public class MyReflectDemo2 { public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class clazz = Class.forName("Reflect.Student" ); Constructor[] cons = clazz.getConstructors(); for (Constructor con : cons){ System.out.println(con); } Constructor[] cons2 = clazz.getDeclaredConstructors(); for (Constructor con : cons2){ System.out.println(con); } Constructor con1 = clazz.getDeclaredConstructor(); System.out.println(con1); Constructor con2 = clazz.getDeclaredConstructor(String.class); System.out.println(con2); Constructor con3 = clazz.getDeclaredConstructor(int .class); System.out.println(con3); Constructor con4 = clazz.getDeclaredConstructor(String.class,int .class); System.out.println(con4); int modifiers = con4.getModifiers(); System.out.println(modifiers); Parameter[] parameters = con4.getParameters(); for (Parameter parameter : parameters){ System.out.println(parameter); } con4.setAccessible(true ); Student stu = (Student)con4.newInstance("张三" ,14 ); System.out.println(stu); } }
9.3利用反射获取成员变量 Class类中用于获取成员变量的方法
Field[] getFields();返回所有公共成员变量对象的数组
Field[] getDeclaredFields();返回所有成员变量对象的数组
Field getField(String name);返回单个公共成员变量对象
Field getDeclaredField(String name);返回单个成员变量对象
Filed类中用于创建对象的方法
void set(Object obj,Object value);赋值
Object get(Object obj);获取值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 package Reflect;import java.awt.*;import java.lang.reflect.Field;public class MyReflectDemo3 { public static void main (String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { Class clazz = Class.forName("Reflect.Student" ); Field[] fields = clazz.getFields(); for (Field field : fields){ System.out.println(field); } Field[] fields2 = clazz.getDeclaredFields(); for (Field field : fields2){ System.out.println(field); } Field gender = clazz.getField("gender" ); System.out.println(gender); Field name = clazz.getDeclaredField("name" ); System.out.println(name); Field age = clazz.getDeclaredField("age" ); System.out.println(age); int modifies = name.getModifiers(); System.out.println(modifies); int modifies2 = gender.getModifiers(); System.out.println(modifies2); String n = name.getName(); System.out.println(n); Class<?> type = name.getType(); System.out.println(type); Student stu = new Student ("张三" ,29 ); name.setAccessible(true ); Object value = name.get(stu); System.out.println(value); name.set(stu,"李四" ); System.out.println(stu); } }
9.4利用反射获取成员方法 Class类中用于获取成员方法的方法
Method[] getMethods(); 返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods();返回所有成员方法的数组,不包括继承的
Method getMethod(String name,Class… parameterTypes);返回单个公共成员对象方法
Method getDeclaredMethod(String name,Class… parameterTypes);返回单个成员方法
Method类中用于创建对象的方法
Object invoke(Object obj,Object… args); 运行方法
参数一:用obj对象调用方法
参数二:调用方法的传递参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 package Reflect;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Parameter;public class MyReflectDemo4 { public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { Class clazz = Class.forName("Reflect.Student" ); Method[] methods = clazz.getMethods(); for (Method method:methods){ System.out.println(method); } Method[] methods1 = clazz.getDeclaredMethods(); for (Method method:methods1){ System.out.println(method); } Method method = clazz.getMethod("sleep" ); System.out.println(method); Method method1 = clazz.getDeclaredMethod("eat" ,String.class); System.out.println(method1); int modifies = method.getModifiers(); int modifies2 = method1.getModifiers(); System.out.println(modifies); System.out.println(modifies2); String name = method1.getName(); System.out.println(name); Parameter[] parameters = method1.getParameters(); for (Parameter parameter:parameters){ System.out.println(parameter); } Class[] exceptionTypes = method1.getExceptionTypes(); for (Class exceptionType:exceptionTypes){ System.out.println(exceptionType); } Student s = new Student (); method1.setAccessible(true ); method1.invoke(s,"水果" ); Object obj = method1.invoke(s,"水果" ); System.out.println(obj); } }
反射的作用
获取一个类里面的所有信息,获取到之后,再执行其他的业务逻辑
结合配置文件,动态的创建对象并调用方法