Java从入门到精通2
2023-12-19 11:24:06 12 举报
AI智能生成
总结
作者其他创作
大纲/内容
集合类和数组的不同之处是:数组的长度是固定的,集合的长度是可变的;数组用来存放基本类型的数据,集合用来存放对象的引用。
集合类概述
是层次结构中的跟接口,构成Collection的单位称为元素。Collection接口通常不能直接使用,但该接口提供了添加元素、删除元素、管理数据的方法。由于List接口与Set接口都继承了Collection接口,因此这些方法对List集合与Set集合是通用的。
Collection接口
实现了可变的数组,允许保存所有的元素,包括null,并可以根据索引位置对集合进行快速的随机访问。缺点是向指定的索引位置插入对象或删除对象的速度较慢。(更善于查找)
ArrayList类
采用链表结构保存对象。这种结构的优点是便于向集合中插入和删除对象。需要向集合中插入、删除对象时,使用LinkList类实现的List集合的效率较高;但对于随机访问集合中的对象,使用LinkList类实现List集合的效率较低。(更善于添加和删除)
LinkedList类
List集合
实现Set接口,由哈希表(HashMap实例)支持。它不保证Set集合的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用null元素。
HashSet类
不仅实现了Set接口,还实现了java.util.SortedSet接口,因此TrreeSet类实现的Set集合在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序,即可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序。
TreeSet类
Set集合
基于哈希表的Map接口的实现,此实现提供所有可选的映射操作,并允许使用null值和null键,但必须保证键的唯一性。HashMap类通过哈希表对其内部的映射关系进行快速寻找。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
HashMap类
实现了Map接口,还实现了java.util.SortedMap接口,因此集合中的映射关系具有一定的顺序。但在添加、删除和定位映射关系时,TreeMap类比HashMap类性能稍差。由于TreeMap类实现的Map集合中的映射关系是根据对象按照一定的顺序排列的,因此不允许键对象是null。
TreeMap类
Map集合
集合类
使用枚举类型设置常量设置常量时,我们通常将常量放置在接口中,这样在程序中就可以直接使用该常量不能被修改因为在接口中定义常量时,该常量的修饰符为final与static。常规定义常量的代码如下:
package thirteen; public interface Constants { public static final int Constants_A=1;//常规定义变量代码 public static final int Constants_B=2; }
变量代码,public static final int constants_B=2;}枚举类型出现后逐渐取代了。上述常量定义方式使用枚举类型定义常量的语法如下:
其中, enum 是定义枚举类型的关键字,当需要程序中使用该常量时,可以使用Constants和Constants_A来表示。
使用枚举类型设置常量
枚举类型较传统定义常量的方式,除具有参数类型检测的优势外,还具有其他方面的优势。用户可以将一个枚举类型看作是一个类,它继承于java.lang.Enum类,当定义一个枚举类型时,每一个枚举类型成员都可以看作是枚举类型的一个实例,这些枚举类型成员都默认被final、public、static修饰,所以当使用枚举类型成员时直接使用枚举类型名称调用枚举类型成员即可。由于枚举类型对象继承于java.lang.Enum类,所以该类中一些操作枚举类型的方法都可以应用到枚举类型中。
枚举类型实例包含一个values()方法,该方法将枚举中所有的枚举值以数组的形式返回。
values()方法
枚举类型中静态方法valueOf()可以将普通字符串转换为枚举类型,而compareTo()方法用于比较两个枚举类型对象定义时的顺序。
valueOf()方法与compareTo()方法
枚举类型中的ordinal()方法用于获取某个枚举对象的位置索引值。
ordinal()方法
在枚举类型中,可以添加构造方法,但是规定这个构造方法必须被private修饰符所修饰。
枚举类型中的构造方法
枚举类型声明提供了一种对用户友好的变量定义方法,枚举了某种类型所有可能出现的值。总结枚举类型,它具有以下特点:1.类型安全2.紧凑有效的数据定义3..可以和程序其他部分完美交互4.运行效率高
深入了解枚举类型
枚举
Object类为最上层的父类,很多程序员为了使程序更为通用,设计程序时通常使传入的值与返回的值都以Object类型为主。当需要使用这些实例时,必须正确地将该实例转换为原来的类型,否则在运行时将会发生ClassCastException异常。为了提前预防这种问题,Java提供了泛型机制。其语法如下:
类名<T>
其中,T是泛型的名称,代表某一种类型。开发者在创建该类对象时需要指定T所代表哪种具体的类型。如果不指定具体类型,T则采用Object类型。
定义泛型类时,可以声明多个类型。语法如下:
其中,T1和T2为可能被定义的类型。这样,在实例化指定类型的对象时就可以指定多个类型。例如:
泛型的高级用法包括限制泛型可用类型和使用类型通配符等。
泛型的类型参数只能是类类型,不可以是简单类型,如A<int>这种泛型定义就是错误的。 泛型的类型个数可以是多个。可以使用extends关键字限制泛型的类型。可以使用通配符限制泛型的类型。
泛型
枚举类型与泛型
1.lambda表达式可以用非常少的代码实现抽象方法。2.lambda表达式不能独立执行,因此必须实现函数式接口,并且会返回一个函数式接口的对象。3.lambdab表达式的语法非常特殊
语法格式:()-> 结果表达式 参数-> 结果表达式(参数1,参数2...,参数n)-> 结果表达式
lambda表达式也可以实现复杂方法,将操作符右侧的结果表达式换成代码块即可
语法格式如下:()->{代码块)参数->(代码块}(参数1,参数2,..参数n)->{代码块)
第1行实现无参方法,方法体是操作符右侧代码块。第2行实现只有一个参数的方法,方法体是操作符右侧代码块。第3行实现多参数的方法,方法体是操作符右侧代码块。
lambda表达式的功能归纳总结,语法理解为:
() -> {代码块}这个方法 按照 这样的代码来实现
函数式接口开发者可以常见自定义的函数式接口
例如:interface MyInterface{ void method();}
如果接口中包含一个以上的抽象方法,则不符合函数式接口的规范,这样的接口不能用Iambda表达式创建匿名对象
Iambda表达式实现无参数抽象方法
interface SayHiInterface{ String say();//抽象方法接口 } public class NoParamterDemo { public static void main(String[] args) {//利用匿名内部类补全方法体 //lambda表达式实现发招呼接口,返回抽象方法结果 SayHiInterface pi=()->\"你好啊,这是lanbda表达式\"; System.out.print(pi.say()); } }
结果如下
lambda表达式实现有参抽象方法如果抽象方法中只有一个参数,lambda表达式则可以省略圆括号lambda表达式中的参数不需要与抽象方法的参数名称相同,但顺序必须相同
lambda表达式使用代码块lambda表达式会自动判断返回值类型是否符合抽象方法的定义
Iambda表达式实现函数式接口
Iambda表达式调用外部变量这些外部的变量有些可以被更改,有些则不能。例如,lambda表达式无法更改局部变量的值,但是却可以更改外部类的成员变量(也可以叫做类属性)的值他。lambda表达式无法更改局部变量局部变量在lambda表达式中默认被定义为final(静态)的,也就是说,lambda表达式只能调用局部变量,却不能改变其值。lambda表达式可以更改类成员变量类成员变量是在lambda表达式中不是被final修饰的,所以lambda表达式可以改变其值lambda 表达式可以调用并修改类成员变量的值lambda表达式只是描述了抽象方法是如何实现的,在抽象方法没有被调用前,lambda表达式中的代码并没有被执行,所以运行抽象方法之前类成员变量的值不会发生变化只要抽象方法被调用,就会执行lambda 表达式中的代码,类成员变量的值就会被修改。
Iambda表达式与异常处理lambda 表达式中并有抛出异常的语法,这是因为lambda表达式会默认抛出抽象方法原有的异常,当此方法被调用时则要进行异常处理。
lambda表达式
引用静态方法语法:类名 :: 静态方法名,这里出现的新操作符 :: 这是英文状态的冒号组成的。需要注意的是这个语法中方法名是没有圆括号的。例如:
List<String> list = Arrays.asList(\"A\
在上面的例子中,System.out::println 是一个方法引用。它引用了 System.out 类的静态方法 println。这个方法接受一个参数(在这个例子中是 String 类型),并打印这个参数。
引用成员方法与引用静态方法语法不同,这里操作符左侧的必须是一个对象名,而不是类名。这种语法也可以达到抽象方法按照类成员方法逻辑来实现的目的。
引用带泛型的方法\"::\"操作符支持引用带泛型的方法。除方法外,\"::\"操作符支持引用带泛型的类。
无参数构造方法引用构造方法的语法:类名::new因为构造方法与类名相同,如果操作符左右都写类名,会让操作符误以为是在引用与类名相同的静态方法,这样会导致程序出现bug,所以引用构造方法的语法使用了new关键字。操作符右侧的写new关键字,表示引用构造方法。
引用有参构造方法引用有参构造方法的语法与引用无参数构造方法一样。区别就是函数式接口的抽象方法是有参数的。
引用数组构造方法把数组类型当作泛型。如果方法返回值是泛型,在这种特殊场景下,方法就应该返回一个数组类型的结果。如果要求抽象方法即引用构造方法,又要返回数组类型结果,这种场景下抽象方法的参数就有了另外一个含义:数组个数。抽象方法的参数可以决定返回的数组长度,但数组中的元素并不是有值的,还需要再次赋值。引用数组构造方法的语法也会有所不同,语法如下:类名[]::new
Fuction接口这个接口有以下两个泛型:T:被操作的类型,可以理解为方法参数类型。R:操作结果类型,可以理解为方法的返回类型。Function 接口是函数式接口,所以只有一个抽象方法,但是Function 接口还提供方法以方便开发者对函数逻辑进行更深层的处理。
引用构造方法lambda表达式有3种引用构造方法的语法,分别是引用无参构造方法、引用有参构造方法和引用数组构造方法。
方法的引用
流处理有点类似数据库的 SQL 语句,可以执行非常复杂的过滤、映射、查找和收集功能,并且代码量很少。唯一的缺点是代码可读性不高。
流处理的接口都定义在java.uil.stream 包下。BaseStream接口是最基础的接口,但最常用的是BaseStream 接口的一个子接口——Stream 接口,基本上绝大多数的流处理都是在Stream 接口上实现的。Stream 接口是泛型接口,所以流中操作的元素可以是任何类的对象。Collection 接口新增两个可以获取流对象的方法。第一个方法最常用,可以获取集合的顺序流,方法如下:Stream stream();第二个方法可以获取集合的并行流,方法如下:Stream parallelstream();因为所有集合类都是Collection 接口的子类,如ArrayList类、HashSet类等,所以这些类都可以进行流处理。例如:List list = new ArrayList(); //创建集合Streamcinteger> s = list.stream();//获取集合流对象
Optional类Optional 类是用final 修饰的,所以不能有子类。Optional类是带有泛型的类,所以该类可以保存任何对象的值。从Optional类的声明代码中就可以看出这些特性,JDK中的部分代码如下public final class Optional<T>{private final T value;} Optional 类中有一个叫作value的成员属性,这个属性就是用来保存具体值的。value 是用泛型了修饰的,并且还用了final 修饰,这表示一个 Optional 对象只能保存一个值。
Collectors类Collectors类为收集类,该类实现了java.util.Collector接口。
filter()方法filterO方法是Stream 接口提供的过滤方法。该方法可以将lambda表达式作为参数,然后按照lambda表达式的逻辑过滤流中的元素。过滤出想要的流元素后,还需使用Stream 提供的collectO方法按照指定方法重新封装。
distinct()方法该方法可以去除流中的重复元素,效果与SQL语句中的DISTINCT关键字一样
Iimit()方法Iimit()方法是Stream接口提供的方法,该方法可以获取流中前N个元素
skip方法skip()方法是Stream接口提供的方法,该方法可以忽略流中的前N个元素
数据过滤数据过滤就是在杂乱的数据中筛选出需要的数据,类似 SQL 语句中的WHERE 关键字,给出一定的条件,将符合条件的数据过滤并展示出来。
数据映射数据的映射和过滤概念不同:过滤是在流中找到符合条件的元素,映射是在流中获得具体的数据。 Stream 接口提供了map0方法用来实现数据映射,map()方法会按照参数中的函数逻辑获取新的流对象,新的流对象中元素类型可能与旧流对象元素类型不相同。
该方法会判断流中的元素是否全部符合某一条件,返回结果是boolean值
allMatch()方法
该方法会判断流中的元素是否有符合某一条件
anyMatch()方法
该方法会判断流中的所有元素是否都不符合某一条件
noneMatch()方法
这个方法会返回符合条件的第一个元素
findFirst()方法
数据查找
不仅可以筛选出特殊元素,还可以对元素的属性进行统计计算
数据统计
将流中元素按照指定的条件分开保存数据分组有一级分组和多级分组一级分组:将所有数据按照一个条件进行分类
数据分组
数据收集
流处理
lambda表达式与流处理
文件类:File字节流:InputStream:入 OutputStream:出字符流:Reader:入 Writer:出输入流InputStream类是字节输入流的抽象类,所有字节流的父类。该类中所有方法遇到错误会引发IOException异常。该类中有一些方法read()read(byte[] b)mark(int readlimit)reset()skip() 输出流
输入/输出流
操作:创建或者删除状态:文件是否存在或者隐藏创建文件对象new File(String Pathnname)File file = new File(“d:/1.txt”)new File(String parent,String child)new File(File parent,String child)
File类
FileInputStream类与FileOutputStream类都用来操作磁盘文件。如果用户的文件读取需求比较简单,则可以使用FileInputStream类,该类继承自InputStream类。FileOutputStream类与FileInputStream类对应,提供了基本的文件写入能力。FileOutputStream类是OutputStream类的子类。FileInputStream类常用的构造方法如下:FileInputStream(String name)。FileInputStream(File file)。第一个构造方法使用给定的文件名name创建一个FileInputStream对象,第二个构造方法使用File对象创建FileInputStream对象。第一个构造方法比较简单,但第二个构造方法允许在把文件连接输入流之前对文件做进一步分析。FileOutputStream类有与FileInputStream类相同的参数构造方法,创建一个FileOutputStream对象时,可以指定不存在的文件名,但此文件不能是一个已被其他程序打开的文件。下面的实例就是使用FileInputStream类与FileOutputStream类实现文件的读取与写入功能的。
说明虽然Java在程序结束时自动关闭所有打开的流,但是当使用完流后,显式地关闭所有打开的流仍是一个好习惯。一个被打开的流有可能会用尽系统资源,这取决于平台和实现。如果没有将打开的流关闭,当另一个程序试图打开另一个流时,可能会得不到需要的资源。
FileInputStream与FileOutputStream类
使用FileOutputStream类向文件中写入数据与使用FileInputStream类从文件中将内容读出来,都存在一点不足,即这两个类都只提供了对字节或字节数组的读取方法。由于汉字在文件中占用两个字节,如果使用字节流,读取不好可能会出现乱码现象,此时采用字符流FileReader类或FileWriter类即可避免这种现象。FileReader类和FileWriter类对应了FileInputStream类和FileOutputStream类。FileReader类顺序地读取文件,只要不关闭流,每次调用read()方法就顺序地读取源中其余的内容,直到源的末尾或流被关闭。
FileReader和FileWriter类
文件输入/输出流
缓存是I/O的一种性能优化。缓存流为I/O流增加了内存缓存区,使得在流上执行skip()、mark()和reset()方法都成为可能。
BufferedInputStream与BufferedOutputStream类
BufferedReader类与BufferedWriter类分别继承Reader类与Writer类。这两个类同样具有内部缓存机制,并能够以行为单位进行输入/输出。
BufferedReader与BufferedWriter类
带缓存的输入/输出流
I/O(输入/输出)
class类
在通过下列一组方法访问构造方法时,将返回Constructor类型的对象或数组。每个Constructor对象代表一个构造方法,利用Constructor对象可以操纵相应的构造方法:
getConstructors()。getConstructor(Class<?>...parameterTypes)。getDeclaredConstructors()。getDeclaredConstructor(Class<?>...parameterTypes)。
如果是访问指定的构造方法,需要根据该构造方法的入口参数的类型来访问。例如,访问一个入口参数类型依次为String型和int型的构造方法,通过下面两种方式均可实现:
访问构造方法
在通过下列一组方法访问成员变量时,将返回Field类型的对象或数组。每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量:
getFields()。getField(String name)。getDeclaredFields()。getDeclaredField(String name)。
如果是访问指定的成员变量,可以通过该成员变量的名称来访问。例如,访问一个名称为birthday的成员变量,访问方法如下:
object. getDeclaredField(\"birthday\");
访问成员变量
在通过下列一组方法访问成员方法时,将返回Method类型的对象或数组。每个Method对象代表一个方法,利用Method对象可以操纵相应的方法:
如果是访问指定的方法,需要根据该方法的名称和入口参数的类型来访问。例如,访问一个名称为print、入口参数类型依次为String型和int型的方法,通过下面两种方式均可实现:
objectClass.getDeclaredMethod(\"print\
案例:
构造成员方法
反射
定义Annotation类型在定义Annotation类型时,也需要用到用来定义接口的interface关键字,但需要在interface关键字前加一个“@”符号,即定义Annotation类型的关键字为@interface,这个关键字的隐含意思是继承了java.lang.annotation.Annotation接口。例如,下面的代码就定义了一个Annotation类型:
public @interface NoMemberAnnotation { }
上面定义的Annotation类型@NoMemberAnnotation未包含任何成员,这样的Annotation类型被称为marker annotation。下面的代码定义了一个只包含一个成员的Annotation类型:
public @interface OneMemberAnnotation{ String value();}
String:成员类型。可用的成员类型有String、Class、primitive、enumerated和annotation,以及所列类型的数组。value:成员名称。如果在所定义的Annotation类型中只包含一个成员,通常将成员名称命名为value。
下面的代码定义了一个包含多个成员的Annotation类型:
public @interface MoreMemberAnnotation{ String desctibe(); Class type();}
在为Annotation类型定义成员时,也可以为成员设置默认值。例如,下面的代码在定义Annotation类型时就为成员设置了默认值:
public @interface DefaultValueAnnotation{ String describe() default \"<默认值>\"; Class type() default void.class;}
在定义Annotation类型时,还可以通过Annotation类型@Target来设置Annotation类型适用的程序元素种类。如果未设置@Target,则表示适用于所有程序元素。枚举类ElementType中的枚举常量用来设置@Targer。
通过Annotation类型@Retention可以设置Annotation的有效范围。枚举类RetentionPolicy中的枚举常量用来设置@Retention,如表16.7所示。如果未设置@Retention,Annotation的有效范围为枚举常量CLASS表示的范围。
定义Annotation类型
如果在定义Annotation类型时将@Retention设置为RetentionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的Annotation信息,如获取构造方法、字段和方法的Annotation信息。Constructor类、Field类和Method类均继承了AccessibleObject类,在AccessibleObject中定义了3个关于Annotation的方法。其中,方法isAnnotationPresent(Class<? extends Annotation> annotationClass)用来查看是否添加了指定类型的Annotation,如果是则返回true,否则返回false;方法getAnnotation(Class<T> annotationClass)用来获得指定类型的Annotation,如果存在则返回相应的对象,否则返回null;方法getAnnotations()用来获得所有的Annotation,该方法将返回一个Annotation数组。在Constructor类和Method类中还定义了方法getParameterAnnotations(),用来获得为所有参数添加的Annotation,将以Annotation类型的二维数组返回,在数组中的顺序与声明的顺序相同。如果没有参数则返回一个长度为0的数组;如果存在未添加Annotation的参数,将用一个长度为0的嵌套数组占位。
访问Annotation信息
Annotation注解功能
反射与注释
第一步:注册驱动
接下来,你需要创建一个连接到你的MySQL数据库的连接对象。这需要你的数据库的URL,用户名和密码。下面是一个例子:
String url = \"jdbc:mysql://localhost:3306/mydatabase\"; String user = \"root\"; String password = \"1234\
在上面的例子中,“localhost:3306”是你的MySQL服务器的地址和端口(通常为3306),“mydatabase”是你的数据库名,“root”和“1234”是你的用户名和密码。
第二步:获取连接
第三步:获取statement对象
查询操作下面这个例子中代码会连接到一个名为\"testDB\"的MySQL数据库,并从\"Users\"表中查询所有的记录。查询的结果会显示每条记录的\"name\"和\"email\"字段。
import java.sql.*; public class Main { public static void main(String[] args) { // 创建连接 String url = \"jdbc:mysql://localhost:3306/testDB\"; String username = \"root\"; String password = \"password\
.增、删、改操作对于插入、更新和删除操作(增删改操作),我们首先需要创建一个PreparedStatement对象,然后设置SQL语句中的参数,并使用executeUpdate()方法执行这个语句。且增删改操作的不同点在于使用不同的SQL语句来创建PreparedStatement对象,其余并无差距。
第四步:执行SOL语句返回结果集
遍历结果集
在执行查询后,你需要处理查询的结果,并且清理你的资源。下面是一个例子:
while(rs.next()) { String column1 = rs.getString(\"column1\"); int column2 = rs.getInt(\"column2\"); //...处理结果... } rs.close(); // 关闭ResultSet stmt.close(); // 关闭Statement conn.close(); // 关闭Connection
关闭连接释放资源
数据库操作
String包的层次结构和继承关系如下 :
常用的Swing组件如下表:
Swing概述
JFrame 类的常用构造方法包括以下两种形式:public JFrame():创建一个初始不可见、没有标题的窗体。span style=\"font-size:inherit;\
Swing常用窗体
JDialog对话框
JOptionPane提供了4种创建对话框的方法,如下:
参数说明如下:parentComponent:指明对话框在哪个窗体上显示,如果传入具体的窗体对象,对话框会在该窗体居中位置显示,如果传入null则在屏幕中间弹出对话框。message:提示的信息。optionType:指定可用于对话框的选项的整数:DEFAULT_OPTION、YES NO_OPTION.YES NO_CANCEL_OPTION 或 OK_CANCEL_OPTION。messageType:指定消息种类的整数,主要用于确定来自可插入外观的图标ERRORMESSAGE、INFORMATION_MESSAGE、WARNING_MESSAGE、QUESTION_MESSAGE 或 PLAIN_MESSAGE。icon:在对话框中显示的图标。options:指示用户可能选择的对象组成的数组。如果对象是组件,则可以正确呈现,非String对象使用其toString方法呈现;如果此参数为null,则由外观确定选项。initialValue:表示对话框的默认选择的对象,只有在使用options 时才有意义,可以为null。
.自定义对话框
确认框
.输入框
.通知框
JOptionPane 小型对话框
null绝对布局
FlowLayout 流布局管理器
BorderLayout 边界布局管理器
GridLayout 网络布局管理器
常用布局管理器
JPanel面板继承java.awt.Container类。JPanel面板必须在窗体容器中使用,无法脱离窗体显示。
JPanel 面板
ScrollPane面板是带滚动条的面板,被用于在较小的窗体中显示较大篇幅的内容。需要注意的是,JScrollPane滚动面板不能使用布局管理器,且只能容纳一个组件。如果需要向JScrollPane面板中添加多个组件,那么需要先将多个组件添加到JPanel面板,再将JPanel面板添加到JScrollPane滚动面板。
JScrollPane 滚动面板
常用面板
JLable 标签
在Swing 程序设计中,图标经常被添加到标签、按钮等组件,使用javax.swing.Imagelcon类可以依据现有的图片创建图标。ImageIcon类实现了Icon接口,它有多个构造方法,常用的如下:public ImagelconO:创建一个 Imagelcon 对象,创建 ImageIcon对象后,使用其调用 setImage(Image image)方法设置图片。public Imagelcon(Image image):依据现有的图片创建图标。public ImageIcon(URL url):依据现有图片的路径创建图标。
图标的使用
JButton 按钮
单选按钮
按钮组
JCheckBox 复选框
JRadinButton 单选按钮
按钮组件
文字标签组件与图标
JComboBox 类的常用构造方法如下:public JComboBox(ComboBoxModeldataModel):创建一个 JComboBox对象,下拉列表中的列表项使用ComboBoxModel中的列表项,ComboBoxModel 是一个用于组合框的数据模型。public JComboBox(Object[]arrayData):创建一个包含指定数组中的元素的JComboBox对象。public JComboBox(Vector vector):创建一个包含指定 Vector 对象中的元素的JComboBox 对象.Voetor对象中的元素可以通过整数索引进行访问,而且 Vector 对象中的元素可以根据需求被添加或者移除。
JComboBox类的常用方法及其说明如表所示。
JComboBox 下拉列表框
JList类的常用构造方法如下:public void JList():创建一个空的JList对象。public void JList(Object[] listData):创建一个显示指定数组中的元素的JList对象。public void JList(Vector listData):创建一个显示指定 Vector 中的元素的JList对象。public void JList(ListModel dataModel):创建一个显示指定的非 null模型的元素的JList对象。
JList 列表框
列表组件
JTextField文本框
JPasswordField 密码框
JTextArea 文本域
文本组件
创建表格
DefaultTableModel 表格数据模型
表格中的数据内容需要予以维护,如使用getValueAt()方法获得表格中某一个单元格的值,使用addRow()方法向表格中添加新的行,使用setValueAt()方法修改表格中某一个单元格的值,使用removeRow()方法从表格中删除指定行等。注意当删除表格模型中的指定行时,每删除一行,其后所有行的索引值将相应地减1,所以当连续删除多行时,需要注意对删除行索引的处理。
维护表格模型
表格组件
动作事件(ActionEvent)监听器是Swing中比较常用的事件监听器,很多组件的动作都会使用它监听,如按钮被单击等。表18.9描述了动作事件监听器的接口与事件源等。
ActionEvent动作事件
当向文本框中输入内容时,将发生键盘事件。KeyEvent类负责捕获键盘事件,可以通过为组件添加实现了KeyListener接口的监听器类来处理相应的键盘事件。
KeyEvent键盘事件
所有组件都能发生鼠标事件,MouseEvent类负责捕获鼠标事件,可以通过为组件添加实现了MouseListener接口的监听器类来处理相应的鼠标事件。
MouseEvent鼠标事件
事件监听器
Swing程序设计
绘图是高级程序设计中非常重要的技术。例如,应用程序可以绘制闪屏图片、背景图片、组件外观等,Web程序可以绘制统计图、数据库存储的图片资源等。正所谓“一图胜千言”,使用图片能够更好地表达程序运行结果,并且能够进行细致的数据分析与保存等。
Graphics类是所有图形上下文的抽象基类,它允许应用程序在组件以及闭屏图像上进行绘制。Graphics类封装了Java支持的基本绘图操作所需的状态信息,主要包括颜色、字体、画笔、文本、图像等。
Graphics类提供了绘图常用的方法,利用这些方法可以实现直线、矩形、多边形、椭圆、圆弧等形状和文本、图片的绘制操作。另外,在执行这些操作之前,还可以使用相应的方法设置绘图的颜色和字体等状态属性。
Graphics类
使用Graphics类可以完成简单的图形绘制任务,但是它所实现的功能非常有限,如无法改变线条的粗细、不能对图片使用旋转和模糊等过滤效果。Graphics2D类继承Graphics类,实现了功能更加强大的绘图操作的集合。由于Graphics2D类是Graphics类的扩展,也是推荐使用的Java绘图类
Graphics2D类
Java绘图类
Java可以分别使用Graphics类和Graphics2D类绘制图形,Graphics类使用不同的方法实现不同图形的绘制。例如,drawLine()方法可以绘制直线,drawRect()方法用于绘制矩形,drawOval()方法用于绘制椭圆形等。
Graphics2D类是在继承Graphics类的基础上编写的,它包含了Graphics类的绘图方法并添加了更强的功能,在创建绘图类时推荐使用该类。Graphics2D类可以分别使用不同的类来表示不同的形状,如Line2D类、Rectangle2D类等。
要绘制指定形状的图形,需要先创建并初始化该图形类的对象,且这些图形类必须是Shape接口的实现类;然后使用Graphics2D类的draw()方法绘制该图形对象,或者使用fill()方法填充该图形对象。语法格式如下:draw(Shape form)或fill(Shape form)其中,form是指实现Shape接口的对象。java.awt.geom包中提供了如下常用的图形类,这些图形类都实现了Shape接口:Arc2D类。CubicCurve2D类。Ellipse2D类。Line2D类。Point2D类。QuadCurve2D类。Rectangle2D类。RoundRectangle2D类。
绘制图形
Java语言使用Color类封装颜色的各种属性,并对颜色进行管理。另外,在绘制图形时还可以指定线的粗细和虚实等画笔属性。
Color类定义了常用色彩的常量值,如表19.2所示。这些常量都是静态的Color对象,可以直接使用这些常量值定义的颜色对象。
设置颜色
BasicStroke类构造方法的参数说明:
设置画笔
绘图颜色与画笔属性
Java绘图类也可以用来绘制文本内容,且可以在绘制前设置字体的样式、大小等。
其中,字体样式可以使用Font类的PLAIN、BOLD和ITALIC常量
设置字体
显示文字
绘制文本
绘图类不仅可以绘制图形和文本,还可以使用drawImage()方法将图片资源显示到绘图上下文中,而且可以实现各种特效处理,如图片的缩放、翻转等。
该方法将img图片显示在x、y指定的位置上。方法中涉及的参数说明
drawImage()方法的使用与绘制文本的drawString()方法类似,唯一不同的是该方法需要指定要通知的图像观察者。
显示图片
开发高级的桌面应用程序,必须掌握一些图像处理与动画制作的技术,如在程序中显示统计图、销售趋势图、动态按钮等。
放大与缩小
图像翻转
图像旋转需要调用Graphics2D类的rotate()方法,该方法将根据指定的弧度旋转图像。语法如下:rotate(double theta)其中,theta是指旋转的弧度。
图像旋转
图像倾斜
图像处理
Java绘图
Windows操作系统是多任务操作系统,它以进程为单位。一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程。也就是说每个正在执行的程序都是一个进程。系统可以分配给每一个进程有一段有限的使用CPU的时间(也可以称为CPU时间片),CPU在这段时间中执行某个进程,然后下一个时间片又跳至另一个进程中去执行。由于CPU转换比较快,所以使得每个进程好像是同时执行一样。下图表明了Windows操作系统的执行模式。
Thread 类是java.lang包中的一个类,从这个类中实例化的对象代表线程,程序员启动一个新线程需要建立Thread实例。Thread类中常用的两个构造方法如下:public Thread():创建一个新的线程对象。public Thread(String threadName):创建一个名称为threadName的线程对象。继承Thread类创建一个新的线程的语法如下:public class ThreadTest extends Threadf {}
继承Thread类
图20.2表明了实现Runnable接口创建线程的流程。
实现Runnable接口
创建线程
虽然多线程看起来像同时执行,但事实上在同一时间点上只有一个线程被执行,只是线程之间切换较快,所以才会使人产生线程是同时进行的假象。在Windows操作系统中,系统会为每个线程分配一小段CPU时间片,一旦 CPU时间片结束就会将当前线程换为下一个线程,即使该线程没有结束。要使线程处于就绪状态,有以下几种方法:调用sleep()方法调用wait()方法。等待输入/输出完成。
线程的生命周期
操作线程有很多方法,这些方法可以使线程从某一种状态过渡到另一种状态
一种能控制线程行为的方法是调用sleep()方法,sleep()方法需要一个参数用于指定该线程休眠的时间,该时间以毫秒为单位。sleep()方法语法如下:try{ Thread.sleep(2000);}catch(InterruptedException e){ e.printStackTrace(();}
.线程的休眠
当某一个线程使用join()方法加入另外一个线程时,另一个线程会等待该线程执行完毕后再继续执行。
线程的加入
以往有的时候会使用stop()方法停止线程,但当前版本的JDK早己废除了stop()方法,不建议使用stop()方法来停止一个线程的运行。现在提倡在run()方法中使用无限循环的形式,然后使用一个布尔型标记控制循环的停止。 如果线程是因为使用了slcep()或wait()方法进入了就绪状态,可以使用Thread 类中 interrupt()方法使线程离开run()方法,同时结束线程,但程序会抛出InterruptedException异常,用户可以在处理该异常时完成线程的中断业务处理,如终止while循环。
线程的中断
操作线程的方法
每个线程都具有各自的优先级,线程的优先级可以表明在程序中该线程的重要性,如果有很多线程处于就绪状态,系统会根据优先级来决定首先使哪个线程进入运行状态。但这并不意味着低优先级的线程得不到运行,而只是它运行的概率比较小,如垃圾回收线程的优先级就较低。 Thread类中包含的成员变量代表了线程的某些优先级,如Thread.MIN_PRIORITY(常数1)、Thread.MAXPRIORITY(常数10)、Thread.NORM PRIORITY(常数5)。其中,每个线程的优先级都在 Thread.MIN_PRIORITY~Thread.MAX_PRIORITY,在默认情况下其优先级都是Thread.NORM PRIORITY。每个新产生的线程都继承了父线程的优先级。 在多任务操作系统中,每个线程都会得到一小段CPU时间片运行,在时间结束时,将轮换另一个线程进入运行状态,这时系统会选择与当前线程优先级相同的线程予以运行。系统始终选择就绪状态下优先级较高的线程进入运行状态。处于各个优先级状态下的线程的运行顺序如图20.8所示。
在图20.8中,优先级为5的线程A首先得到CPU时间片;当该时间结束后,轮换到与线程A相同优先级的线程B;当线程 B的运行时间结束后,会继续轮换到线程A,直到线程A与线程B都执行完毕,才会轮换到线程C;当线程C结束后,才会轮换到线程D。线程的优先级可以使用 setPriority()方法调整,如果使用该方法设置的优先级不在1~10,将产生IllegalArgumentException异常。
Thread 类中提供了一种礼让方法,使用yield()方法表示,它只是给当前正处于运行状态的线程个提醒,告知它可以将资源礼让给其他线程,但这仅是一种暗示,没有任何一种机制保证当前线程会将资源礼让。yield()方法使具有同样优先级的线程有进入可执行状态的机会,在当前线程放弃执行权时会再度回到就绪状体。对于支持多任务的操作系统来说,不需要调用yield()方法,因为操作系统会为线程自动分配CPU时间片来执行。
线程的礼让
线程的优先级
实际开发中,使用多线程程序的情况很多,如银行排号系统、火车站售票系统等。这种多线程的程序通常会发生问题,以火车站售票系统为例,在代码中判断当前票数是否大于0,如果大于0则执行将该票出售给乘客的功能,但当两个线程同时访问这段代码时(假如这时只剩下一张票),第一个线程将票售出,与此同时第二个线程也已经执行完成判断是否有票的操作,并得出票数大于0的结论,于是它也执行售出操作,这样就会产生负数。所以,在编写多线程程序时,应该考虑到线程安全问题。实质上线程安全问题来源于两个线程同时存取单一对象的数据。
线程安全
Java 中提供了同步机制,可以有效地防止资源冲突。同步机制使用synchronized关键字,使用该关键字包含的代码块称为同步块,也称为临界区,语法如下:synchronized(Object) {}通常将共享资源的操作放置在 synchronized 定义的区域内,这样当其他线程获取到这个锁时,就必须等待锁被释放后才可以进入该区域。Object 为任意一个对象,每个对象都存在一个标志位,并具有两个值,分别为0和1。一个线程运行到同步块时首先检查该对象的标志位,如果为0状态,表明此同步块内存在其他线程,这时当期线程处于就绪状态,直到处于同步块中的线程执行完同步块中的代码后,这时该对象的标识位设置为1,当期线程才能开始执行同步块中的代码,并将Object对象的标识位设置为0,以防止其他线程执行同步块中的代码。
同步块
同步方法就是在方法前面用synchronized关键字修饰的方法,其语法如下:synchronized void f(){}当某个对象调用了同步方法时,该对象上的其他同步方法必须等待该同步方法执行完毕后才能被执行。必须将每个能访问共享资源的方法修饰为synchronized,否则就会出错。
同步方法
线程同步机制
线程同步
多线程
计算机网络实现了多台计算机间的互联,使得它们彼此之间能够进行数据交流。网络应用程序就是在已连接的不同计算机上运行的程序,这些程序借助于网络协议,相互之间可以交换数据。编写网络应用程序前,首先必须明确所要使用的网络协议。TCP/IP协议是网络应用程序的首选
网络程序设计编写的是与其他计算机进行通信的程序。Java已经将网络程序所需要的元素封装成不同的类,用户只要创建这些类的对象,使用相应的方法,即使不具备有关的网络知识,也可以编写出高质量的网络通信程序。
为了实现两台计算机的通信,必须用一个网络线路连接两台计算机
服务器是指提供信息的计算机或程序,客户机是指请求信息的计算机或程序。网络用于连接服务器与客户机,实现两者间的相互通信。但是,有时在某个网络中很难将服务器与客户机区分开。我们通常所说的局域网(Local Area Network,LAN),就是一群通过一定形式连接起来的计算机,它可以由两台计算机组成,也可以由同一区域内的上千台计算机组成。将LAN延伸到更大的范围,这样的网络称为广域网(Wide Area Network,WAN)。我们熟悉的互联网(Internet),就是由无数的LAN和WAN组成的。
局域网与互联网
网络协议规定了计算机之间连接的物理、机械(网线与网卡的连接规定)、电气(有效的电平范围)等特征,计算机之间的相互寻址规则,数据发送冲突的解决方式,长数据如何分段传送与接收等内容。就像不同的国家有不同的法律一样,目前网络协议也有多种。下面简单地介绍几个常用的网络协议。
IP是Internet Protocol的简称,是一种网络协议。Internet网络采用的协议是TCP/IP协议,其全称是Transmission Control Protocol/Internet Protocol。Internet依靠TCP/IP协议,在全球范围内实现了不同硬件结构、不同操作系统、不同网络系统间的互联。在Internet网络上存在着数以亿计的主机,每台主机都用网络为其分配的Internet地址代表自己,这个地址就是IP地址。到目前为止,IP地址用4个字节,也就是32位的二进制数来表示,称为IPv4。为了便于使用,通常取用每个字节的十进制数,并且每个字节之间用圆点隔开来表示IP地址,如192.168.1.1。现在人们正在试验使用16个字节来表示IP地址,这就是IPv6,但IPv6还没有投入使用。|TCP/IP模式是一种层次结构,共分为4层,分别为应用层、传输层、互联网层和网络层。各层实现特定的功能,提供特定的服务和访问接口,并具有相对的独立性。
IP协议
网络协议
在TCP/IP协议栈中,有两个高级协议是网络应用程序编写者应该了解的,即传输控制协议(Transmission Control Protocol,TCP)与用户数据报协议(User Datagram Protocol,UDP)。TCP协议是一种以固接连线为基础的协议,它提供两台计算机间可靠的数据传送。TCP可以保证数据从一端送至连接的另一端时,能够确实送达,而且抵达的数据的排列顺序和送出时的顺序相同。因此,TCP协议适合可靠性要求比较高的场合。就像拨打电话,必须先拨号给对方,等两端确定连接后,相互才能听到对方说话,也知道对方回应的是什么。HTTP、FTP和Telnet等都需要使用可靠的通信频道。例如,HTTP从某个URL读取数据时,如果收到的数据顺序与发送时不相同,可能就会出现一个混乱的HTML文件或是一些无效的信息。UDP是无连接通信协议,不保证数据的可靠传输,但能够向若干个目标发送数据,或接收来自若干个源的数据。UDP以独立发送数据包的方式进行。这种方式就像邮递员送信给收信人,可以寄出很多信给同一个人,且每一封信都是相对独立的,各封信送达的顺序并不重要,收信人接收信件的顺序也不能保证与寄出信件的顺序相同。UDP协议适合于一些对数据准确性要求不高,但对传输速度和时效性要求非常高的网站,如网络聊天室、在线影片等。这是由于TCP协议在认证上存在额外耗费,可能使传输速度减慢,而UDP协议即使有一小部分数据包遗失或传送顺序有所不同,也不会严重危害该项通信。
TCP与UDP协议
一般而言,一台计算机只有单一的连到网络的物理连接(Physical Connection),所有的数据都通过此连接对内、对外送达特定的计算机,这就是端口。网络程序设计中的端口(port)并非真实的物理存在,而是一个假想的连接装置。端口被规定为一个在0~65535的整数。HTTP服务一般使用80端口,FTP服务使用21端口。假如一台计算机提供了HTTP、FTP等多种服务,那么客户机会通过不同的端口来确定连接到服务器的哪项服务上,如图21.3所示。通常,0~1023的端口数用于一些知名的网络服务和应用,用户的普通网络应用程序应该使用1024以上的端口数,以避免端口号与另一个应用或系统服务所用端口冲突。网络程序中的套接字(Socket)用于将应用程序与端口连接起来。套接字是一个假想的连接装置,就像插座一样可连接电器与电线,如图21.4所示。Java将套接字抽象化为类,程序设计者只需创建Socket类对象,即可使用套接字。
端口与套接字
网络程序设计基础
TCP网络程序设计是指利用Socket类编写通信程序。利用TCP协议进行通信的两个应用程序是有主次之分的,一个称为服务器程序,另一个称为客户机程序,两者的功能和编写方法大不一样。
java.net包中的InetAddress类是与IP地址相关的类,利用该类可以获取IP地址、主机地址等信息。
InetAddress类
java.net包中的ServerSocket类用于表示服务器套接字,其主要功能是等待来自网络上的“请求”,它可通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。如果多台客户机同时提出连接请求,服务器套接字会将请求连接的客户机存入列队中,然后从中取出一个套接字,与服务器新建的套接字连接起来。若请求连接数大于最大容纳数,则多出的连接请求被拒绝。队列的默认大小是50。
ServerSocket类
明白了TCP程序工作的过程,就可以编写TCP服务器程序了。在网络编程中,如果只要求客户机向服务器发送消息,不要求服务器向客户机发送消息,称为单向通信。客户机套接字和服务器套接字连接成功后,客户机通过输出流发送数据,服务器则通过输入流接收数据。
TCP网络程序设计
TCP程序
用户数据报协议(UDP)是网络信息传输的另一种形式。基于UDP的通信和基于TCP的通信不同,基于UDP的信息传递更快,但不提供可靠性保证。使用UDP传递数据时,用户无法知道数据能否正确地到达主机,也不能确定到达目的地的顺序是否和发送的顺序相同。虽然UDP是一种不可靠的协议,但如果需要较快地传输信息,并能容忍小的错误,可以考虑使用UDP。
DatagramPacket类
DatagramSocket类
根据前面所讲的网络编程的基本知识以及UDP网络编程的特点,下面创建一个广播数据报程序。广播数据报是一项较新的技术,其原理类似于电台广播。广播电台需要在指定的波段和频率上广播信息,收听者也要将收音机调到指定的波段、频率,才可以收听广播内容。
创建UDP协议广播电台程序package wanluo; import java.io.IOException;import java.net.*; public class Notification extends Thread{ String weather = \"节日预报:八点有大型晚会,请收听\";//发送的消息 int port = 9898;//端口 InetAddress iaddress = null; MulticastSocket socket = null;//多点广播套接字 @SuppressWarnings(\"deprecation\") Notification(){ try { iaddress = InetAddress.getByName(\"224.255.10.0\
接收广播程序。单击“开始接收”按钮,系统开始接收主机播出的信息;单击“停止接收”按钮,系统停止接收广播主机播出的信息。代码如下:
发出广播和接收广播的主机地址必须位于同一个组内,地址范围为224.0.0.0~224.255.255.255,该地址并不代表某个特定主机的位置。加入同一个组的主机可以在某个端口上广播信息,也可以在某个端口上接收信息。
UDP网络程序设计
UDP程序
网络通信
Java从入门到精通2
收藏
0 条评论
回复 删除
下一页