异常:就是程序在运行时出现不正常情况。将问题封装成对象就是异常。
异常由来:问题也是现实生活中一个具体事务,也可以通过 java 的类的形式进行描述。并封装成对象。其实就是 java 对不正常情况进行描述后的对象体现。
Throwable
|---Error //通常出现重大问题如:运行的类不存在或者内存溢出等。
|---Exception //运行时出现的一起情况
|---RuntimeException //特殊异常类,抛时不需要声明
Exception和Error的子类名都是以父类名作为后缀。
异常体系的特点:
1)异常体系中的所有类以及建立的对象都具备可抛性。
2)也就是说可以被throw和throws关键字所操作。
1)编译时被检测异常:
该异常在编译时,如果没有处理(没有抛也没有try),编译失败。该异常被标识,代表着可以被处理。
2)运行时异常(编译时不检测):
在编译时,不需要处理,编译器不检查。该异常的发生,建议不处理,让程序停止,需要对代码进行修正例如:RuntimeException以及其子类。
4、throw和throws
throw定义在函数内,用于抛出异常对象。
throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。
当函数内容有throw抛出异常对象,并未进行try处理。必须要在函数上声明,否则编译失败。
Note:throws 和 throw 的区别:
throws 使用在函数上(写在小括号和大括号之间)。throw 使用在函数内。
throws 后面跟的异常类。可以跟多个。用逗号隔开。throw 后跟的是异常对象。
常见方法操作:
String getMessage();//获取异常的信息。返回字符串。
toString();//获取异常类名和异常信息,返回字符串。
printStackTrace(); //获取异常类名和异常信息,以及异常出现在程序中的位置.返回值void.
//其实JVM默认的异常处理机制,就是在调用printStackTrace方法,打印异常的堆栈的跟踪信息。
1)自定义异常必须是自定义类继承 Exception。
原因:异常体系有一个特点,因为异常类和异常对象都被抛出,他们都具备可抛性。这个可抛性是 Throwable 这个体系中独有特点,只有 Throwable 体系中的类和对象才可以被 throws 和 throw 操作。
2)自定义异常时:如果该异常的发生,无法在继续进行运算,就让自定义异常继承RuntimeException。
@H_408_301@ 3) 当自定义了异常类继承Exception后,如果未在类中定义异常信息,那么通过toString方法打印出来的结果就只有自定义的异常类名,不会显示异常信息。
4) 要定义自定义异常的信息时,可以使用父类已经定义好的功能。异常信息传递给父类的构造函数。因为父类中已经把异常信息的操作都完成了。所以子类只要在构造时,将异常信息传递给父类通过super语句。那么就可以直接通过getMessage方法获取自定义的异常信息。 示例如下:
class MyException extends Exception { private String msg; MyException(String msg) { super(msg);// 返回自定义的输入信息 } }6、异常的好处:
1)将问题进行封装。
2)将正常流程代码和问题处理代码相分离,方便于阅读。
7、异常的处理原则:
1)处理方式有两种:try 或者 throws。
2)调用到抛出异常的功能时,抛出几个,就处理几个。一个 try 对应多个 catch。多个 catch,父类的 catch 放到最下面。
3)catch 内,需要定义针对性的处理方式。不要简单的定义 printStackTrace,输出语句。也不要不写。
4)当捕获到的异常,本功能处理不了时,可以继续在 catch 中抛出。
8、异常的注意事项:
1)问题能在内部解决就解决,坚决不再往外抛出。
2)catch是用于处理异常的,如果没有catch就代表异常没有被处理,如果该一场是编译时异常那必须要进行声明。
3)在子父类覆盖时:子类抛出的异常必须是父类的异常的子类或者子集。如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能再抛。
小练习示例:
/* 老师使用电脑讲课。 描述电脑: 1、电脑运行 2、电脑重启 描述电脑问题: 1、电脑蓝屏了 2、电脑起火了 描述老师: 1、老师使用电脑 2、老师讲课。 描述老师可能出现的问题: 1、老师不能继续讲课了,他让同学们自己做练习。 */ //电脑蓝屏了 class BlueScreenException extends Exception { BlueScreenException(String message) { super(message); } } //电脑起火了 class FireBreakingException extends Exception { FireBreakingException(String message) { super(message); } } //老师无法继续上课 class StopTeachException extends Exception { StopTeachException(String message) { super(message); } } class Computer { int start=1; //电脑启动 void run()throws BlueScreenException,FireBreakingException { if(start==2) throw new BlueScreenException("Computer_BlueScreen"); else if(start==3) throw new FireBreakingException("Computer_FireBreaking"); System.out.println("Computer_run"); } //电脑重启 void reset() { start=1; System.out.println("Computer_reset"); } } class Teacher { private String name; private Computer cpt; //对老师进行初始化 Teacher(String name) { this.name=name; cpt=new Computer(); } //老师开始讲课 public void teach()throws StopTeachException { try { cpt.run(); } catch (BlueScreenException e) { //System.out.println(e.getMessage()); cpt.reset(); } catch (FireBreakingException e) { test(); //System.out.println(e.getMessage()); throw new StopTeachException("Teather_StopTeach:"+e.getMessage()); } System.out.println(name+"Teacher_teaching"); } void test() { System.out.println("学生做练习"); } } class ExceptionTest { public static void main(String[] args) { Teacher t=new Teacher("毕老师"); try { t.teach(); } catch (StopTeachException e) { System.out.println(e.toString()); System.out.println("换老师或者放假"); } } }二、常用类
概述:存在于java.lang包中,是所有类的根类、超类。Java 中的每一个类都直接或间接地使用Object作为父类,所有对象都实现这个类的方法。所有类对 Object类的继承都是java默认的,无需使用 extends 明确表示。Object 类中提供了 11 个成员方法,也就是说所有其他类都具备这 11 个方法。其中最常用的方法:
public boolean equals(Object obj); //比较两个对象是否相等
public String toString(); //返回该对象的字符串表示
void finalize(); // 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
Class getClass(); //获取对象的字节码文件的描述类,后面再讲反射的时候还会在说这个类。String name = s.getClass().getName();
int hashCode(); // 获取对象的哈希值。其实就是对象的内存地址值十进制表示若自定义类中有与 Object 类中相同的方法功能,没有必要重新定义。
//只要沿袭父类中的功能,建立自己特有的内容即可,也就是覆盖。
equals():我们获取对象后,比较它的地址值意义不大。所以也会对这个方法进行重写。重写要完成什么功能,是根据需求定的。
"==" 和 equals 的用法:
"==":
1)可以用于比较基本数据类型,比较的就是基本数据类型的值是否相等。
2)可以用于比较引用数据类型,比较的是对象的地址值是否相等。
equals:
1)equals 只能用于比较引用数据类型的。
2)Object 提供的 equals 是用于比较对象地址值是否相同。
3)自定义类中,如果重写了 equals 方法,那么就是按照你自己的需求来比较的。
toString():
表示格式:getClass().getName()+"@"+Integer.toHexString(hashCode());一般我们输出对象名的时候,其实底层调用的就是该对象的 toString()方法。这种返回没有意义,所以,我们会重写这个方法,显示类的成员变量信息。
2、String类:
概述:多个字符组成的一个序列,叫字符串。生活中很多数据的描述都采用的是字符串的,而且我们还会对其进行操作。字符串是一个特殊的对象,是一个被 final 修饰的类,所以不可能有子类。字符串一旦初始化就不可以被改变(此处指的是内存中的地址值不可改变)。
eg: String s = new String();
s = "hello";
2)String(byte[] bys): 传一个字节数组作为参数
eg: byte[] bys = {97,98,99,100,101};
String s = new String(bys);
3)String(byte[] bys,int index,int length):把字节数组的一部分转换成一个字符串
eg:byte[] bys = {97,101};
String s = new String(bys,1,2);
4)String(char[] chs): 传一个字符数组作为参数
eg:char[] chs = {'a','b','c','d','e'};
String s = new String(chs);
5)String(char[] chs,int length):把字符数组的一部分转换成一个字符串
eg:char[] chs = {'a','e'};
String s = new String(chs,3);
6)String(String str):把一个字符串传递过来作为参数
eg:String ss = new String(s);
7)直接把字符串常量赋值给字符串引用对象(最常用)
eg:String s = "hello";
常见方法: @H_408_301@ 1)获取 @H_408_301@ 1.1字符串中包含的字符数,也就是字符串的长度 @H_408_301@ int length()://获取长度。 @H_408_301@ 1.2根据位置获取位置上的某个字符 @H_408_301@ char charAt(int index)://当访问到字符串中不存在的角标时,会发生字符串角标越界的错误。 @H_408_301@ 1.3根据字符获取该字符存在字符串的位置 @H_408_301@ int indexOf(int ch)://返回的是ch在字符串中第一次出现的位置。//传入的是字符对应的ASCII码。//如果没有找到,返回-1。 @H_408_301@ int indexOf(int ch,int fromIndex)://从fromIndex指定位置开始,获取ch在字符串中出现的位置。 @H_408_301@ int indexOf(String str)://返回的是str在字符串中第一次出现的位置。
@H_408_301@ int indexOf(String str,int fromIndex)://从fromIndex指定位置开始,获取str在字符串中出现的位置。 @H_408_301@ int lastIndexOf()://反向索引 @H_408_301@ 2)判断 @H_408_301@ 2.1字符串中是否包含某一个子串 @H_408_301@ boolean contains(str); @H_408_301@ Note:indexOf(str)可以索引str第一次出现的位置,如果返回-1表示该str不在字符串中存在。所以,也可以用于对指定判断是否包。如:if(str.indexOf(“aa”)!=-1)而且该方法既可以判断,又可以获取出现的位置。如果只为判断,用contains。 @H_408_301@ 2.2字符串中是否有内容 @H_408_301@ boolean isEmpty();//原理就是判断长度是否为0。 @H_408_301@ 2.3字符串是否是以指定内容开头 @H_408_301@ boolean startsWith(str); @H_408_301@ 2.4字符串是否是以指定内容结尾 @H_408_301@ boolean endsWith(str); @H_408_301@ 2.5判断字符串内容是否相同,复写了Object类中的equals方法 @H_408_301@ boolean equals(str); @H_408_301@ 2.6判断内容是否相同,并忽略大小写。 @H_408_301@ boolean equalsIgnoreCase(); @H_408_301@ 3)转换 @H_408_301@ 3.1将字符数组转成字符串 @H_408_301@ 构造方法:String(char[]); @H_408_301@ String(char[],offset,count);//将字符数组中的一部分转成字符串。 @H_408_301@ 静态方法: @H_408_301@ static String copyValueOf(char[]); @H_408_301@ static String copyValueOf(char[] data,int offset,int count ); @H_408_301@ static String valueOf(char[]); @H_408_301@ 3.2将字符串转成字符数组 @H_408_301@ char[] tocharArray(); @H_408_301@ 3.3将字节数组转成字符串 @H_408_301@ String(byte[]); @H_408_301@ String(byte[],count);//将字节数组中的一部分转成字符串。count表示个数。 @H_408_301@ 3.4将字符串转成字节数组 @H_408_301@ byte[] getBytes(); @H_408_301@ 3.5将基本数据类型转成字符串 @H_408_301@ String valueOf(int); @H_408_301@ String valueOf(double); @H_408_301@ Note:字符串和字节数组在转换过程中,是可以指定编码表的。 @H_408_301@ 4)替换 @H_408_301@ String replace(oldchar,newchar);//返回的是一个新字符串。如果要替换的字符不存在,返回的还是原字符串。 @H_408_301@ 5)切割 @H_408_301@ String[] split(regex);//涉及到正则表达式的点,不能作为切割字符串的regex。 @H_408_301@ 6)子串,获取字符串中的一部分 @H_408_301@ String substring(begin);//从指定位置开始到结尾。如果角标不存在,会出现字符串角标越界异常。 @H_408_301@ String substring(begin,end);//包含头,不包含尾。 @H_408_301@ 7)转换,去除空格,比较 @H_408_301@ 7.1将字符串转成大写或小写 @H_408_301@ String toUpperCase(); @H_408_301@ String toLowerCase(); @H_408_301@ 7.2将字符串两端的多个空格去除 @H_408_301@ String trim(); @H_408_301@ 7.3对两个字符串进行自然顺序的比较 @H_408_301@ int compareTo(String); 基于上述知识点,几个小练习演示如下所示:
/* * 练习:1、字符串反转 * 2、获取一个字符串在另一个字符串中出现的次数 * 3、有两个字符串,找出两个字符串中最大相同那个字符串 */ public class StringTest { // 1、字符串反转 public static String reverseString(String str) { char[] ar = str.tocharArray();// 将字符串转成字符数组 reverse(ar);// 将字符数组进行反转 return new String(ar);// 返回反转后的字符串 } // 逐个调换字符数组中的对应位置的字符 public static void reverse(char[] ar) { for (int i = 0,j = ar.length - 1; i < j; i++,j--) { swap(ar,i,j); } } // 自定义反转数组中的两个元素 private static void swap(char[] ar,int i,int j) { char temp = ar[i]; ar[i] = ar[j]; ar[j] = temp; } // 2、获取一个字符串在另一个字符串中出现的次数 public static int getNumOfString(String str,String key) { int num = 0;// 定义计数器 int index = 0;// 定义脚标,用于记录查询位置 while ((index = str.indexOf(key,index)) != -1) { // indexOf(key) 或者indexOf(key,beginIndex)都可以 // str = str.substring(index + key.length()); index = index + key.length();// 下一次的查询其实位置是前一次查询返回值加上字符串长度,以此保证每次都是往后偏移查询 num++;// 查到一次,计数器自增1 } return num; } // 3、有两个字符串,找出两个字符串中最大相同那个字符串 public static String getMaxSubString(String str1,String str2) { // 不论传进来的两个字符串谁更长,自定义maxString、minString来指向长字符串和短字符串 String maxString = str1.length() > str2.length() ? str1 : str2; String minString = maxString == str1 ? str2 : str1; String maxSubString = null; for (int i = 0; i < minString.length(); i++) {// 控制在最短字串长度内 // 依次递减短字符串子串 for (int j = 0,k = minString.length() - i; k <= minString.length(); j++,k++) { maxSubString = minString.substring(j,k);// 获取短字符串的子串 if (maxString.indexOf(maxSubString) != -1) {// 如果包含在长字符串中则表明找到了 return maxSubString; } } } return "-1"; } public static void main(String[] args) { String str = "abc cde"; String s1 = "ascasfhelloasfasf v"; String s2 = "ashellolkkd"; System.out.println(reverseString(str)); System.out.println(getNumOfString(str,"c")); System.out.println(getMaxSubString(s2,s1)); } }结果如下所示:
3、StringBuffer类
概述:字符缓冲区类,是一个容器,一个线程安全的可变字符序列。 StringBuffer 可以对字符串内容进行增删改查等操作,很多方法和 String 相同。
4、StringBuilder类
概述:StringBuilder在JDK1.5 版本之后出现的,一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换, 用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,简易优先采用 StringBuilder 类,因为此类比 StringBuffer 效率高。
StringBuilder 和 StringBuffer 的功能是一样的,但是有区别:
StringBuffer(JDK1.0)是线程安全的。一般用于多线程。
StringBuilder(JDK1.5)不保证线程安全。一般用于单线程。
Note:一般来说,我们写的程序都是单线程的,所以,用 StringBuilde,效率高,以后开发建议使用 StringBuilder。
5、System类
概述:System类包含一些有用的类字段和方法。它不能被实例化。在System类提供的设施中,有标准输入、标准输出和错误输出流;对外部定义的属性和环境变量的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法。其中的属性和方法全是静态。
字段摘要:
err “标准”错误输出流
in “标准”输入流;默认是键盘
out “标准”输出流;默认是控制台
方法:
static void setIn(InputStream in) 重新分配“标准”输入流
static void setOut(PrintStream out) 重新分配“标准”输出流
static void arraycopy(Object src,int srcPos,Object dest,int destPos,intlength);从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。
static long currentTimeMillis(); 返回以毫秒为单位的当前时间。
exit(int status); 退出当前虚拟机。0 之外的表示非正常退出。
static void gc(); 运行垃圾回收器
getProperty(); 获取指定键提示的系统属性
static Properties getProperties(); 获取系统属性信息,确定当前的系统属性。
//因为 Properties 是 Hashtable 的子类,也就是 Map 集合的一个子类对象。 那么可以通过map 的方法取出该集合中的元素。该集合中存储都是字符串。没有泛型定义。
6、Runtime类
概述:每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。可以通过 getRuntime()方法获取当前运行时,应用程序不能创建自己的Runtime 类实例。
理解:此类没有提供构造函数。因不能直接 new 创建自己的类对象,会联想到类中所有方法都是静态的。但是该类中还有非静态方法。说明该类肯定会提供了方法获取本类对象。而且该方法是静态的,并返回值类型是本类类型。由这个特点可以看出该类使用了单例设计模式完成。该方式为:static Runtime getRuntime(); //返回与当前 Java 应用程序相关的运行时对象。
其他方法:
Process exec(String conmand); //在单独的进程中执行指定的字符串命令。
7、Date类
概述:表示特定的瞬间,精确到毫秒。在 JDK1.1 开始,使用 Calendar 类实现日期和时间字段之间转换。使用 DateFormat 类来格式化和解析日期字符串。Date 中的相应大部分方法已废弃。UTC 为世界标准时间。GMT 为民间标准(格林威治标准时)
构造方法:
public Date();//分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒)。
public Date(long Date);//分配 Date 对象并初始化此对象,以表示自从标准基准时间(称为“历元(epoch)”,即 1970 年 1 月 1 日 00:00:00GMT)以来的指定毫秒数。
方法摘要:
int compareTo(Date anotherDate) // 比较两个日期的顺序。
boolean equals(Object obj) //比较两个日期的相等性。
public void getTime(); //返回当前时间的毫秒值
public void setTime(); //设置当前毫秒值
boolean after(Date when); //测试此日期是否在指定日期之后。
boolean before(Date when);// 测试此日期是否在指定日期之前。
long 与 Date 类型转换:
System.currentTimeMillions();//获取系统当前时间,返回值 long 类型
Date.getTime();(注:需先创建 Date 对象)
Date 与 String 类型转换:
public final String format(Date date);
获取系统时间的两种方法的区别:
第一种:
Date time=new Date(); //创建时间对象
第二种:
long l=System.currentTimeMillis();//获取系统当前时间
Date d=new Date(l);
System.out.println(d);
分析:两种方法的 Date 时间运行的结果相同,它们都创建时间对象 Date,区别在于第二种方法时间对象引用了系统的 long 型时间。 而 System.currentTimeMillis()方法返回值为 long 型,还可以利用此方法计算应用程序的运行时间。
8、DateFormat与SimpleDateFormat类
DateFormat:使用与语言无关的方式格式化和并解析日期和时间。是一个日期格式化子类的抽象类。该类可以进行格式化也可以解析字符串。
方法:
String format(Date date);//将 Date 日期格式化为日期时间字符串。
SimpleDateFormat(); // 用默认的模式和默认语言环境的日期格式符号构造 SimpleDateFormat。
SimpleDateFormat(String pattern); //参数 Date,创建格式对象。用给定的模式和默认语言环境的日期格式符号构造
格式化日期时间步骤:
1)在创建对象时指定一个格式:YYYY 年 MM 月 dd 日 HH:mm:ss (如果调用格式化器无参构造,此步骤省略)
2)创建一个格式器 SimpleDateFormat
3)创建一个日期对象 Date d
4)使用格式化器的 formate 方法格式化 d,得到想要的格式字符串。
Note:hh 表示 12 小时制(1—12),HH 表示 24 小时制(0—23),更多日期和时间模式请参考SimpleDateFormat类的API说明
示例如下:
import java.text.SimpleDateFormat; import java.util.Date; /* * Date类: * 1、获取系统当前时间 * 2、利用SimpleDateFormat类格式化指定时间 */ public class DateDemo { public static void main(String[] args) { // 第一种获取方式 Date date1 = new Date(); // 第二种获取方式 long time = System.currentTimeMillis(); Date date2 = new Date(time); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒"); String needDate = sdf.format(date2); System.out.println("系统时间戳:" + date2); System.out.println("格式化时间:" + needDate); System.out.println("格式化模板:" + sdf.toPattern()); } }结果如下:
9、Calendar类
概述:Calendar 是一个抽象类。时间点(某一时刻)
方法:
getInstance(); //获取日历(使用默认时区和语言环境获取一个日历),不是通过子类创建,而是通过 父类方法 getInstance()返回一个 Calendar对象。
int get(int field);//参数是日历字段值,月份的统计是从 0 到 11 的
void set(); //设置日历字段。
abstract void add(int field,int amount); //根据日历规则,为给定的日历字段添加或者减去指定的时间量。
以下返回值类型为 int:
年: calendar.get(Calendar.YEAR);
月: calendar.get(Calendar.MONTH);
日: calendar.get(Calendar.DAY_OF_MONTH);
星期: calendar.get(Calendar.DAY_OF_WEEK);
时: calendar.get(Calendar.HOUR_OF_DAY);
分: calendar.get(Calendar.MINUTE);
秒: calendar.get(Calendar.SECOND);
示例如下:
import java.util.Calendar; /* * Calendar类: * set() 给指定日历设置给定值 * get() 获取指定字段 * * add() 在指定时间上加上一个指定的值再显示 */ public class CalendarDemo { public static void main(String[] args) { // 获取某年2月的天数,例如2012年的2月有几天 Calendar c = Calendar.getInstance(); // 3月1日减一天就是2月的最后一天,Calendar月份范围0-11 c.set(2012,2,1); c.add(Calendar.DAY_OF_MONTH,-1); System.out.println(c.get(Calendar.YEAR) + "年" + (c.get(Calendar.MONTH) + 1) + "月共有" + c.get(Calendar.DAY_OF_MONTH)); // 日历设置到2个月后 c.add(Calendar.MONTH,2); System.out.println("日历设置到2个月后是" + c.get(Calendar.YEAR) + "年" + (c.get(Calendar.MONTH) + 1) + "月" + c.get(Calendar.DAY_OF_MONTH) + "日"); } }结果如下:
10、Math类(静态工具类)
Math:包含用于数学基本运算的方法。
字段摘要:
E: 自然对数的底数。 (double)
PI: π,即圆周与直径之比。 (double)
方法:
abs(); //绝对值
cbrt(); //立方根
ceil(); //返回大于等于参数的最小整数(double)特别注意负数的值
floor(); //返回小于等于参数的最小整数(double)
round(); //四舍五入(int 或 long) 原理:原数加 0.5 判断
random(); //伪随机数 (0——1 之间的数,不包含 1)
max(); //返回两个数中最大值
min(); //返回两个数中最小值
Note: 此处的 random 类与 Math 类中的 random()方法作用类似。Random 类可以生成对象,用其下的 next()方法或者 nextInt()方法生成伪随机数。 其中有方法:
int next(int bits); //生成下一个伪随机数
int nextInt(int n); //返回下一个伪随机数,在 0 与指定值(不包括指定值)之间均匀分布的 int 值。
三、GUI
1、概述:
GUI:Graphical User Interface(图形用户接口)。用图形的方式,来显示计算机的操作图形界面。方便、直观。
CLI:Command line User Interface(命令行用户接口)。就是 DOS 命令行操作。不直观。
Java 为 GUI 提供的对象,都存在 java.Awt 和 javax.Swing 两个包中。Java中对于图形化编程有个完整的继承体系:
Awt 与 Swing:
java.Awt: (Abstract Window Toolkit,抽象窗口工具集),需要调用本地系统方法实现功能。属重量级控件。跨平台性较弱。
javax.Swing:在 AWT 基础上,建立一套图形界面系统,其中提供了更多组件,而且完全由 Java 实现。增强了可移植性,属轻量级控件。
Note:开发时,制作图形化界面时,一般需要导入两个包,import java.awt.*; 和 import java.awt.event.*;。
2、布局管理器
布局:容器中组件的排放方式。
常见的布局管理器:
FlowLayout(流式布局管理器):从左到右的顺序排列。Panel 默认的布局管理器。
BorderLayout(边界布局管理器):东南西北中。Frame 默认的布局管理器。
GridLayout(网络布局管理器):规则的矩阵。
GardLayout(卡片布局管理器):选项卡。
GridBagLayout(网格包布局管理器):非规矩的矩阵。
3、Component
Component 是一个具有图形表示能力的对象,可在屏幕上显示,并可与用户进行交互。常用子类:Window、Panel(面板,不能单独存在)。Window 常用子类:Frame、DialogFrame 类:是带有标题和边框的顶层窗口。若显示窗体,必须设置 setVisible 显示。设置 Frame 时,有一个默认的管理器是边界式布局(BorderLayout) 。
主要方法:
add() //添加组件(含参数)
setVisible(Boolean b) //根据参数的值来显示或隐藏组件
setSize() //设置窗体大小,参数为窗口的横坐标和纵坐标
setLocation() //设置窗体在本地位置,参数为横、纵坐标
setLayout() //设置布局管理器(参数可以是相应布局管理器的对象)
setBounds() //移动组件并调整其大小,参数是 4 个坐标(左边距、右边距、宽、高)
addMouseListener() //添加指定的鼠标监听器
addKeyListener() //添加键盘监听事件
创建图形化界面的步骤:
1)创建 frame 窗体。
2)对窗体进行基本设置。比如大小,位置,布局。
3)定义组件。
4)将组件通过窗体的 add 方法添加到窗体中。
5)让窗体显示,通过 setVisible(true)
4、事件监听机制
组成:
事件源、事件(Event)、监听器(Listener)、事件处理(引发事件后处理方式)
事件源:就是 awt 包或者 swing 包中的那些图形界面组件。
事件:每一个事件源都有自己特有对应事件和共性事件。
监听器:将可以触发某一个事件的所有动作都封装到监听器中。
事件处理:对时间元传来的信息进行处理并反馈出去。
Note:在 java 中事件源、事件(Event)、监听器(Listener)都已定义好,直接获取其对象使用。只需要做事件处理(对产生的动作进行处理)。
5、Window(窗体事件)
Window :
addWindowListener( ) //添加窗口事件监听器
windowListener 接口:复写方法,实例化对象,才能使用。但它有一个已复写全部方法的子类WindowAdapter。
WindowAdapter:接收窗口事件的抽象适配器类。此类中的方法为空。它是一个没有抽象方法的抽象类,目的是不能创建对象。此类存在的意义是方便创建监听器对象。使用: 因为 WindowListener 的子类 WindowAdapter 已经实现了 WindowListener 接口。并覆盖了其中的所有方法。那么我只要继承自 Windowadapter 覆盖我需要的方法即可。具体方法如下:
windowClosing( ) //关闭窗口
windowIconified( ) //窗口最小化状态
windowOpened() //打开窗口
windowActivated() //前置窗口
windowClosed() //关闭窗口
wind owDeactivated() //后置窗口
6、Button(含 Action 事件)
方法:
addActionListener() //添加指定的动作监听器
ActionListener 接口:用于接收操作事件的监听器接口。 是少数没有适配器接口的其中一个。其中只有一个方法 actionPerformed(),作用:发生操作时调用。
7、鼠标事件和键盘事件
MouseListener: 用于接收组件上“感兴趣的”鼠标事件(eg:按下、释放、单击、进入或离开)的监听器接口。有适配器。
方法:
mouseClicked(MouseEvent e) //鼠标单击(按下并释放)
mouseEntered(MouseEvent e) //鼠标进入组件
mouseExited(MouseEvent e) //鼠标离开组件
mousePressed(MouseEvent e) //鼠标按下时
mouseReleased(MouseEvent e) //鼠标释放时
Note:鼠标按下与 Action 事件同时存在操作时,鼠标按下先发生。
MouseEvent: (适配器)
成员变量:static int mouse_clicked
方法:
int getClickCount() //返回鼠标单击次数
keyListener: 有适配器。
static int VK_ENTER
keyPressed(keyEvent e) //按下某个键时调用此方法
keyReleased(keyEvent e) //释放某个键时调用此方法
keyTyped(keyEvent e) //键入某个键时调用此方法
keyEvent: (适配器)
char getkeyChar() //返回与此事件中的键相关联的字符
int getkeyCode() //获取键盘对应的码
static String getKeyText(int keyCode) //通过码获取对应的键盘字符
Note:InputEvent 类中 isControlDown() 判断 ctrl 键是否被按下;InputEvent 类中 consume() 以非默认方式处理事件,屏蔽键
8、TextField 和 TextArea
TextField: 文本框类;TextArea:文本区域
构造方法:TextField() //创建文本框。带参数可以设置文本框大小,只能指定列(宽)。
TextArea() //创建文本区域,既能指定行数又能指定列数,还可以指定文本区域内含有的默认文字
方法:
append(String str) //追加文本。将给定文本追加到文本区的当前文本在他们的父类 TextComponent 中,
String getText() //获取文本的方法
setText() //设置填充文本内容,参数为内容
9、Dialog 和 Label
Dialog: 是一个带标题和边界的顶层窗口。对话框,默认边界布局管理器,一般对话框不能单独存在,必须依赖于窗体。
FileDialog: 是 Dialog 的子类。显示一个对话框窗口,用户可以从中选择文件。构造参数可以有模式:FileDialog.LOAD(打开,加载文件)和 FileDialog.SAVE(保存)默认打开。
方法:
String getFile() //获取选定文件
String getDirectory() //获取文件对话框目录
Label: 标签,最常用的控件之一,setText()来设置指定文本
10、MenuBar、MenuItem、Menu
MenuBar: 封装绑定到框架的菜单栏的平台概念。为了将该菜单栏与Frame对象关联,可以调用该框架的setMenuBar方法,add()用来添加菜单栏。
MenuItem:菜单项
Menu:菜单条,其中add()用来将指定菜单项或者标签添加到菜单栏。
Note:MenuBar 包括 Menu,Menu 包括 MenuItem、Menu(带箭头)。MenuBar 为菜单栏,一般一个窗口中只有一个;Menu 菜单项,可以设置多个,若并排显示,都添加进 MenuBar;若显示在菜单项中(带二级箭头菜单条) ,则 Menu 嵌套 (添加)Menu 即可。MenuItem 子菜单,是最终子菜单。可以设置多个,添加进 Menu。
GUI示例如下:
/* GUI:文本框和文本区域功能等(对话框) */ import java.awt.*; import java.awt.event.*; import java.io.*; public class MyWindowDemo { private Frame f; private TextField tf; private Button but; private TextArea ta; private Dialog d; private Label lab; private Button okBut; MyWindowDemo() { init(); } public void init() { f = new Frame("my window"); f.setBounds(300,600,500); f.setLayout(new FlowLayout()); tf = new TextField(60); but = new Button("转到"); ta = new TextArea(25,70); // 此处不应该直接初始化对话框等组件,一般处理用户出错问题再创建使用对话框 // 这里只为演示看效果。 d = new Dialog(f,"提示信息-self",true); d.setBounds(400,200,240,150); d.setLayout(new FlowLayout()); lab = new Label(); okBut = new Button("确定"); d.add(lab); d.add(okBut); // 注意:不要将对话框添加到frame中,只有出现问题才会调用出现对话框 f.add(tf); f.add(but); f.add(ta); myEvent(); f.setVisible(true); } private void myEvent() { okBut.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { d.setVisible(false); } }); d.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { d.setVisible(false); } }); tf.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) showDir(); } }); but.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { showDir(); } }); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } private void showDir() { String dirPath = tf.getText(); File dir = new File(dirPath); if (dir.exists() && dir.isDirectory()) { ta.setText("");// 清空文本 String[] names = dir.list(); for (String name : names) { ta.append(name + "\r\n");// 追加文本 } } else { String info = "您输入的信息:" + dirPath + "是错误的。请重输"; lab.setText(info); d.setVisible(true); } } public static void main(String[] args) { new MyWindowDemo(); } }结果如下:
四、正则表达式
1、概述:符合一定规则的表达式。一些特殊符号的使用。
作用:用于操作字符串
特点:用于一些特定的字符串来表达一些代码操作---到达简化效果
好处:可以简化对字符串的校验操作
弊端:符号定义越多,正则越长,阅读性极差
2、正则表达式构造摘要(非捕获组)主要:
----字符类:只能规则一个字符
[abc] 判断字符串当中某一个字符位上出现的字符。字符是 a、b 或 c。
[^abc] 任何字符,只要不是 a、b、c 即可。
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)
[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)
[a-z&&[def]] d、e 或 f(交集)
----预定义字符类:这里的\不是转义字符。使用时,记得用\\
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f \r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
----Greedy 数量词:x 代表规则,当字符不确定或者很多的时候
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
----边界匹配器:
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(若有)
\z 输入的结尾
3、具体操作功能:
1)匹配:String matches(regex)
2)切割:String[] split(String regex)
3)替换:String replaceAll(String regex,String replacement)String 类中方法:
4)获取:将字符串中符合规则的子串取出,具体操作步骤如下:
a)将正则表达式封装成对象
b)让正则对象和药操作的字符串相关联
d)通过引擎对符合规则的子串进行取出
4、功能选择:
1)只想知道是否正确————>匹配
2)想要将已有的字符串便称另一个字符串————>替换
3)想要按照自己的规则将字符串变成多个子串————>切割
4)想要拿到符合需求的字符串子串————>获取
示例1:
import java.util.regex.Matcher; import java.util.regex.Pattern; /* * 正则表达式: * 作用:用于操作字符串 * 特点:用于一些特定的字符串来表达一些代码操作---到达简化效果 * 好处:可以简化对字符串的校验操作 * 弊端:符号定义越多,正则越长,阅读性极差 * * 具体操作功能: * 1、匹配:String matches(regex) * 2、切割:String[] split(String regex) * 3、替换:String replaceAll(String regex,String replacement) * 4、获取:将字符串中符合规则的子串取出 * 操作步骤: * 1)将正则表达式封装成对象 * 2)让正则对象和药操作的字符串相关联 * 3)获取正则匹配引擎 * 4)通过引擎对符合规则的子串进行取出 * * */ public class RegexDemo { public static void main(String[] args) { System.out.println("---------checkQQ-----------"); checkQQ(); System.out.println("---------regexDemo1-----------"); regexDemo1(); System.out.println("---------checkPhonenum-----------"); checkPhonenum(); System.out.println("---------splitDemo-----------"); splitDemo(); System.out.println("---------replaceAllDemo-----------"); replaceAllDemo(); System.out.println("---------getDemo-----------"); getDemo(); } // 获取 public static void getDemo() { String str = "zhong guan cong hei ma di shi er qi jiu yao kai ban le."; System.out.println("字符串:" + str); String regex = "\\b[a-z]{4}\\b"; // 将规则封装成对象 Pattern p = Pattern.compile(regex); // 让正则对象和要作用的字符串相关联,获取匹配器对象 Matcher m = p.matcher(str); // String类中的matches()用的就是Pattern和Matcher对象来完成的,仅仅为了使用简单而封装的,功能单一 // 将规则作用到字符串上,并进行符合规则的子串查找 // boolean flag = m.find(); // System.out.println(flag); // System.out.println(m.group());// 用于获取匹配后的结果 System.out.println("获取结果为:"); while (m.find()) { System.out.println(m.group()); System.out.println(m.start() + "..." + m.end()); } } // 替换 public static void replaceAllDemo() { String str = "wwwwwwwitheimaaaaacom"; // 用“#”替换数字 // String repstr = str.replaceAll("\\d{5,}","#"); // 将叠词替换& // String repstr = str.replaceAll("(.)\\1+","&"); // 将重叠的字母替换成单个字母,用$n(n为前面的组标识)获取前面的组 String repstr = str.replaceAll("(.)\\1+","$1"); System.out.println("字符串:" + str + "替换后结果为:" + repstr); } // 切割 public static void splitDemo() { String str = "wwwkkitheimaqqcom"; // str = "d:\\abc\\a.txt"; // .代表任何字符(与行结束符可能匹配也可能不匹配)要使用必须转义 \\. // String regex = "\\."; // 路径分隔符\\对应的regex为\\\\ // String regex = "\\\\"; // 按照叠词切割. // 为了让规则的结果被重用,可以讲规则封装成一个组,用()完成。 // 组的出现都有编号,从1开始,要想使用就可以通过\n(n为租的编号)表示 String regex = "(.)\\1+"; String[] arr = str.split(regex); System.out.println("切割结果如下:"); for (String ar : arr) { System.out.println(ar); } } // 匹配测试1 public static void regexDemo1() { String str = "a111111"; String regex = "[a-z]\\d{3,5}"; System.out.println("匹配测试1" + str.matches(regex)); } // 匹配手机号:手机号段 13xxx 15xxx 18xxx public static void checkPhonenum() { String phone = "18767330882"; String regex = "1[358]\\d{9}"; boolean flag = phone.matches(regex); if (flag) { System.out.println("验证手机号" + phone + "---is ok"); } else { System.out.println("验证手机号" + phone + "---is wrrong"); } } // 验证QQ号,不能0开头,5-15位,不能有字符 public static void checkQQ() { String qq = "1512465"; String regex = "[1-9]\\d{4,14}"; boolean flag = qq.matches(regex); if (flag) { System.out.println("验证QQ号" + qq + "---is ok"); } else { System.out.println("验证QQ号" + qq + "---is wrrong"); } } }结果如图所示:
示例2:
import java.util.Collections; import java.util.TreeSet; /* * 功能选择: * 1、只想知道是否正确————>匹配 * 2、想要将已有的字符串便称另一个字符串————>替换 * 3、想要按照自己的规则将字符串变成多个子串————>切割 * 4、想要拿到符合需求的字符串子串————>获取 */ public class RegexTest { public static void main(String[] args) { System.out.println("----------regexTest1----------"); regexTest1(); System.out.println("----------ipSort----------"); ipSort(); System.out.println("----------checkMail----------"); checkMail(); } // 对邮件地址进行验证。 public static void checkMail() { String mail = "cavenzzep@163.com.cn"; String regex = "\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}"; System.out.println(mail.matches(regex)); } // * 练习需求: 将下面的字符串转换成(我要进黑马) public static void regexTest1() { String str = "我我...我我...我要...要要要...要去...去去去...去北京...京京京"; // 将已有的字符串变成另一个字符串————>替换 // 1、先将.去掉 // 2、将重复的内容变成单个子符内容 str = str.replaceAll("\\.+",""); System.out.println(str); str = str.replaceAll("(.)\\1+","$1"); System.out.println(str); } // 将ip地址进行地址段顺序排序 public static void ipSort() { String ip = "192.168.0.1 2.2.2.1 168.192.10.10 10.10.10.10 254.254.254.1 255.255.255.1"; ip = ip.replaceAll("(\\d+)","00$1"); System.out.println(ip); ip = ip.replaceAll("0*(\\d{3})","$1"); System.out.println(ip); String[] ips = ip.split(" "); TreeSet<String> tree = new TreeSet<String>(Collections.reverSEOrder()); for (String newIp : ips) { // System.out.println(newIp); tree.add(newIp); } for (String s : tree) { System.out.println(s.replaceAll("0*(\\d+)","$1")); } } }结果如图所示:
以上所述仅代表个人观点,如有出入请谅解。