Java从入门到精通(12~21章)
2023-12-20 01:17:10 6 举报
AI智能生成
登录查看完整内容
Java从入门到精通(12~21章)总结
作者其他创作
大纲/内容
官方说法将它看成一个容器,集合中的各个对象,很容易将其从集合中取出来,也很容易将其存放到集合中,还可以将其按照一定的顺序进行摆放
相比于数组,集合没有边界,且不会占用过多内存,拿服务器举例,一个用数组来存用户数据,当他的用户数量超过数组长度,数据将存储不下,这时需要停服维护,且你不知道下一次该把数组改多大,会有多少用户注册,另一个使用集合来存储用户数据,当用户量超过当前容量,集合会适当扩大容量,可以把它看作火车,车厢不够可以加,但数组不能,所以相比于数组,集合的用处和实用性都远高于数组
常用的集合类有List集合,Set集合和Map集合,其中List集合和Set集合继承了Collection接口,各接口提供了不同的实现类下图是集合类的继承关系:
集合类概述
Collection接口时层次结构中的接口,构成Collection的单位称为元素,它不能直接使用,但是提供了方法,例如添加元素,删除元素,管理元素。因为List接口和Set接口都继承了Collection接口,所以这些方法,List集合和Set集合都是通用的
下图是Collection接口的常用方法:
运行结果
import java.util.ArrayList;import java.util.Iterator;import java.util.List; public class Gather { public static void main(String[] args) { // TODO Auto-generated method stub List<String>list=new ArrayList<>(); list.add(\"a\"); list.add(\"b\"); list.add(\"c\"); list.add(\"d\"); int i=(int)(Math.random()*list.size()); System.out.println(\"随机获取集合中的元素:\"+list.get(i)); list.remove(3); System.out.println(\"将索引是'3'的元素从集合移除后,集合中的元素是:\"); for(int j=0;j<list.size();j++) { System.out.println(list.get(j)); for(String temp : list) { System.out.println(temp); } System.out.println(\"Inerator迭代打印内容:\"); Iterator<String> it =list.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } }
例题12.2
Collection接口
List接口继承了Collection接口,因此包含Collection接口中的所以方法,此外,它还有两个非常重要的方法
List接口的常用实现类有ArrayList类与LinkedList类
ArrayList类:实现了可变的数组,允许保存所有元素,包括null,并可根据索引位置对集合进行快速的随机访问。缺点就是向指定的u怂恿位置插入对象或删除对象的速度较慢。LinkedList类:采用链表结构保存对象。这种结构的优点是便于向集合中插入和删除对象。需要向集合中插入,删除对象时,使用LinkedList类实现的List集合的效率更高,但对于随机访问合集中的对象,使用LiknedList类实现List集合的效率较低。
实例化List集合的代码如下:
1.List<E> list = new ArrayList<>();2.List<E> list2 = new LinkedList<>();
List接口的实现类
List接口
Set接口常用的实现类有HshSet类与TreeSet类
HashSet类实现Set接口,由哈希表支持,他不保证Set集合的迭代顺序,特别是它不保证顺序恒久不变。此类允许使用null元素TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,因此TreeSet类实现的Set集合在遍历集合时按照自然顺序递增排序,也可按照指定比较器递增排序,即可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序
import java.util.Iterator;import java.util.Set;import java.util.TreeSet; public class TreeSetTest { public static void main(String[] args) { // TODO Auto-generated method stub Set<Integer>set=new TreeSet<>(); set.add(-5); set.add(-7); set.add(10); set.add(6); set.add(3); Iterator<Integer>it=set.iterator(); System.out.print(\"Set集合中的元素:\"); while(it.hasNext()) { System.out.print(it.next()+\" \"); } } }
例题12.3
Set集合
Map集合没有继承Collerction接口,,其提供的是key到value的映射。Map集合中不能包含相同的key,每个key只能映射一个value。
Map接口提供了将key映射到值的对象。一个映射不能包含重复的key,每个key最多只能映射到一个值
Map接口
常用的接口有HashMap类和TreeMap类。
运行结果:
例
Map接口的实现类
Map类
集合类
Java中的枚举是一种特殊的类,它用于定义一组有限的常量。枚举在Java中被视为数据类型,你可以使用它们来创建枚举类型的变量,然后使用那些变量等。枚举类使用enum关键字进行定义。
例如:在这个例子中,我们定义了一个名为Day的枚举类,它包含了一周的七天作为常量。
1、枚举类中只能包含常量和方法,以及构造函数。2、枚举常量必须是public static final类型,每个常量的名称必须唯一。3、枚举类中可以定义构造函数和方法,但这些方法只能访问枚举常量和实例变量。4、枚举常量按照它们的声明顺序在枚举类中进行排序。5、枚举类不能继承其他类或实现接口。6、枚举常量的名称必须是唯一的,不能重复。7、枚举类的构造函数只能有一个,且必须为private类型。8、枚举类中不能使用继承和多态等特性。
定义枚举类时,需要遵循以下规则:
1、定义有限个特定的值:枚举可以用来定义一组有限的特定的值,例如一周的天数,或者颜色等。这些值在程序运行期间是不会改变的。2、作为方法的参数:枚举可以作为方法的参数,这样可以让代码更加清晰,易于阅读和维护。例如,你可以定义一个枚举类型来表示不同的排序方式,然后在方法中使用这个枚举作为参数。3、作为返回类型和参数类型:枚举可以作为方法的返回类型和参数类型。例如,你可以定义一个方法来获取一个枚举类型的列表,或者传递一个枚举类型的对象作为参数。
枚举类型在实际中主要用于以下几个方面:
public enum SortType { ASC(\"升序\
例如:在这个例子中,我们定义了一个枚举SortType来表示不同的排序方式。这个枚举有两个值:ASC和DESC,分别表示升序和降序。我们还为每个值提供了一个字符串描述。
SortType type = SortType.ASC; // 使用 SortType 作为变量类型 System.out.println(type.getValue()); // 输出 \"升序\"
然后我们可以像下面这样使用这个枚举:
public void sortData(SortType type) { // 根据 type 进行排序 // ... } // 调用方法时使用枚举作为参数 sortData(SortType.ASC);
或者在方法中使用:
使用
1、安全:使用枚举可以防止错误地使用无效的值。如果一个方法只接受有限个特定的值作为参数,那么使用枚举可以确保传入的参数是有效的。如果试图传入一个无效的值,编译器将会报错。2、可读性和可维护性:使用枚举可以使代码更加清晰和易于阅读。每个枚举值都可以有一个有意义的名称,而不是一个难以理解的数字或者字符串。同时,如果需要添加新的枚举值,只需要在枚举类中添加新的实例,而不需要修改现有的代码。3、性能:使用枚举可以提高性能。因为枚举值是静态的,所以它们可以在编译期间被解析和优化。相比之下,如果使用一个字符串或者整数来表示相同的信息,那么这些值需要在运行时解析和比较。
优点:
1、占用空间:每个枚举值都会在内存中占用一定的空间。虽然这可能不会对单个程序造成太大的影响,但是如果在一个大型的项目中使用大量的枚举值,那么这可能会成为一个问题。2、可能产生过度设计:如果过度使用枚举,可能会导致代码变得过于复杂和难以维护。例如,如果在一个方法中使用一个包含大量枚举值的列表,那么这可能会使代码变得难以理解和维护。
缺点:
优缺点
枚举类存在的方法,具体详见JavaApi文档1.8
方法
枚举类型与泛型
在Java中,Lambda表达式是一种函数式编程的特性,它允许以简洁的语法编写函数或操作,而无需显式创建匿名类。Lambda表达式在Java 8中引入,是使Java更适应现代编程风格和需求的重要工具。lambda表达式可以代替简单的匿名内部类的实现。lambda表达式的一个重要作用就是能够简写代码。需要注意的是,lambda表达式只适用于函数式接口,也就是接口内只定义了一个方法的接口。如果一个接口是函数式接口一般会使用 @FunctionalInterface 来表示。
例如:forEach遍历中的接口就是一个函数式接口。
(parameters) -> { statements; }
lambda表达式语法
parameters:这是Lambda表达式的参数列表。参数类型是可选的,也可以直接推断。例如,a -> a + 1 和 (int a) -> a + 1 是等效的。->:这是Lambda操作符,将参数列表和Lambda体分开。expression:这是Lambda体的单个表达式。如果Lambda体包含多个语句,则它们必须被大括号 {} 包围。
在小括号()内,如果只有一个形参,或者形象类型只有一种,那么形参类型可以省略在大括号内{},如果只有一条语句,那么 大括号可以省略、return可以省略、分号也可以省略。
需要了解的是在实现 lambd表达式时可以按规则来简写lambda表达式:
以下通过具体案例来说明这个简写规则。首先先定义一个set集合,我们都知道set集合是无索引的,那么set集合常规的遍历方式只有迭代器遍历与forEach遍历。
Set<String> s=new HashSet<>();// set集合:无序、不重复、无索引s.add(\"张三\");s.add(\"李四\");s.add(\"王五\");
// 迭代器方式遍历set集合 // 创建迭代器 Iterator<String> it = s.iterator(); // 判断当前迭代器指针是否指向最后一个位置 while(it.hasNext()){ // 返回迭代器指针当前指向的元素,并且移动迭代器指针 String str = it.next(); System.out.println(str); }
1、迭代器遍历
// foreach循环遍历set集合 for(String i : s){ System.out.println(i); }
2、forEach遍历
以上两种遍历方式都能实现遍历set集合的要求,但是代码还是不够简洁,以下我们来通过从匿名内部类到lambda表达式的改进。
//完整版 s.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } });
匿名内部类
s.forEach((String i) -> { System.out.println(i);});
lambda表达式
s.forEach((o1) -> System.out.println(o1) ); //极简版
根据简化规则的lambda表达式
在Java中,方法引用是一种简化Lambda表达式的方式,它允许你直接引用现有的方法,而不是重新定义一个Lambda表达式。方法引用在Java 8中引入,它是一种非常方便的语法糖,可以使代码更加简洁、易读。常用的方法引用分为引用静态方法、引用成员方法等。
语法:类名 :: 静态方法名,这里出现的新操作符 :: 这是英文状态的冒号组成的。需要注意的是这个语法中方法名是没有圆括号的。
1、引用静态方法
List<String> list = Arrays.asList(\"A\
在上面的例子中,System.out::println 是一个方法引用。它引用了 System.out 类的静态方法 println。这个方法接受一个参数(在这个例子中是 String 类型),并打印这个参数。
引用静态方法规则:
例如:
引用对象的方法是指通过对象来引用其成员方法。方法引用的语法格式为:object::methodName,其中object为对象实例,methodName为对象所属类中的成员方法名。
2、引用成员方法
class Animal { String name; void makeSound() { System.out.println(\"The animal makes a sound\"); } } public class Main { public static void main(String[] args) { Animal animal = new Animal(); animal.name = \"Cat\
在这个示例中,我们定义了一个Animal类,并在Main类中创建了一个Animal对象。我们使用animal::makeSound方法引用了Animal对象的makeSound方法。在printAnimalInfo方法中,我们使用Lambda表达式来处理被引用的方法,同时将Animal对象作为参数传递给该方法。
请注意,这里的MethodReferenceDemo和printAnimalInfo方法需要根据你的实际需求进行相应的实现。
方法引用
Java中的Stream流是一种新的特性,它提供了一种处理集合和数组的方式,可以极大地方便我们对集合、数组等数据源进行连续操作。Stream流可以让我们以一种更加简洁、高效、可读性更强的方式来处理数据。Stream流的操作可以分为中间操作和终止操作两种类型。中间操作返回的是一个新的Stream流,而终止操作返回的是一个非Stream类型的结果。在Stream流的处理过程中,数据是惰性求值的,只有在执行终止操作时才会开始处理数据。这种处理方式可以减少计算量和开销,提高效率。创建Stream流可以从很多种数据源中创建,例如List、Set或者任何其他实现了Iterable接口的类。创建方式很简单,使用stream()或parallelStream()方法即可。总的来说,Stream流是一种方便、简洁且高效的数据处理方式,它可以使代码更加简洁易懂,提高代码的可读性和可维护性。
/* filter:为过滤方法,方法中形参为lambda表达式或实现类 stream流只能使用一次,建议使用链式编程 修改流中的数据,不会改变原数组或集合的值,类似于拷贝了一份进行操作而已 limit:获取stream流中前几个元素,形参为个数 skip:跳过stream流中形参个元素。 distinct:去重方法,当stream对象为自定义方法时,那么需要重写hashcode与equals方法 concat:合并两个stream流 map:转换流中数据类型*/
常用的中间操作方法
/* 总结方法: froEach方法,遍历 count:统计 toArray:将流中数据转换为指定类型数组进行返回。 collect:将流中数据收集进一个集合进行返回*/
需要注意的是,在进行流处理的时候,中间方法与终止方法的区别在于中间方法会返回一个新的stream流,可以需要调用,而终止方法返回的是一个非stream流的结果。所以stream一般适合链式调用。
使用stream流将List集合中的数据添加到map集合中,姓名做键,年龄做值。
示例1:
结果:
以上方法都是使用到了流处理的中间方法与终结方法。
常用的终止方法
Stream流
Iambda表达式与流处理
首先如果我们在Java编写的一个程序中获得了想要的某种结果,那么在程序结束后,这个结果还存在嘛?不存在的,因为在Java程序运行时,程序会被加载到内存中在内存中运行,但是,在程序结束后虚拟机会自动释放内存空间,中间程序得到得结果也会消失,但是我们如果想保存这个结果呢?之前因为我们学习过使用JDBC技术链接数据库,这也能达到目的,但是对于某些长文本数据存储到数据库中就有些不便,那么这次我们学习Java的io技术可以将程序结果存储到本地的文件中,随取随存。
绪论
Java中的输入流是一种用于从外部设备读取数据的机制。它提供了一组类和接口,用于从不同的数据源读取数据,如文件、网络连接、控制台等。Java中的输入流主要分为以下几种类型:
1、字节流(Byte Stream):以字节为单位进行读写操作的流。常见的字节流类包括InputStream和OutputStream。2、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Reader和Writer。3、缓冲流(Buffered Stream):缓冲流可以提高读写效率,减少对外部设备的访问次数。常见的缓冲流类包括BufferedInputStream、BufferedOutputStream、BufferedReader和BufferedWriter。4、数据流(Data Stream):数据流用于读写基本数据类型,如int、float、double等。常见的数据流类包括DataInputStream和DataOutputStream。5、转换流(Conversion Stream):转换流可以将一种类型的流转换为另一种类型的流,例如InputStreamReader可以将字节流转换为字符流。
1、创建输入流对象:根据需要创建相应的输入流对象,例如使用FileInputStream类创建字节流对象读取文件,使用BufferedReader类创建字符流对象读取文本文件。2、打开连接:打开与外部设备的连接,例如使用open()方法打开文件。3、读取数据:通过输入流对象读取数据。在读取数据时,可以使用输入流提供的方法逐个读取字节或字符,也可以使用输入流的读取方法一次读取多个字节或字符。4、关闭连接:关闭与外部设备的连接,例如使用close()方法关闭文件。
常规常见输入流步骤:
输入流
Java中的输出流是一种用于将数据写入到外部设备的机制。它提供了一组类和接口,用于将数据从Java程序输出到不同的目标,如文件、网络连接、控制台等。
Java中的输出流主要分为以下几种类型:
1、字节流(Byte Stream):以字节为单位进行读写操作的流。常见的字节流类包括OutputStream和Writer。2、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。3、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。4、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。5、字符流(Character Stream):以字符为单位进行读写操作的流。常见的字符流类包括Writer和OutputStream。
1、创建输出流对象:根据需要创建相应的输出流对象,例如使用FileOutputStream类创建字节流对象写入文件,使用PrintWriter类创建字符流对象写入文本文件。2、创建输出流对象:根据需要创建相应的输出流对象,例如使用FileOutputStream类创建字节流对象写入文件,使用PrintWriter类创建字符流对象写入文本文件。3、写入数据:通过输出流对象将数据写入到外部设备。在写入数据时,可以使用输出流提供的方法逐个写入字节或字符,也可以使用输出流的写入方法一次写入多个字节或字符。4、关闭连接:关闭与外部设备的连接,例如使用close()方法关闭文件。
使用输出流进行数据写入的一般步骤如下:
在使用输入输出流进行数据读取时,应该遵循“打开-使用-关闭”的原则,及时关闭连接以释放资源。同时,应该根据实际需求选择合适的流类,以达到最佳的读写效果。
需要注意的是:
输出流
Java中的File类是用于文件和目录操作的类。它提供了一种在Java程序中创建、读取、写入和删除文件的方式。File类主要用于对文件增删查的操作,没有用于对文件内部数据的读写功能。
1、创建文件或目录:可以使用File类的构造函数创建一个新的文件或目录。例如,File file = new File(“path/to/file.txt”)将创建一个名为file.txt的文件。如果文件已经存在,则不会创建新文件。2、判断文件或目录是否存在:可以使用File类的exists()方法来判断文件或目录是否存在。如果文件或目录存在,则返回true,否则返回false。3、获取文件或目录的属性:可以使用File类的各种方法获取文件或目录的属性,如文件名、文件大小、文件创建时间等。例如,getName()方法返回文件或目录的名称,length()方法返回文件的大小(以字节为单位),lastModified()方法返回文件最后修改的时间。4、删除文件或目录:可以使用File类的delete()方法删除文件或目录。如果删除成功,则返回true,否则返回false。需要注意的是,如果文件或目录不存在,或者由于其他原因无法删除,则删除操作可能会失败。5、获取文件或目录的路径:可以使用File类的getAbsolutePath()方法获取文件或目录的绝对路径。该路径是一个字符串,表示文件或目录在文件系统中的位置。6、获取文件或目录的路径:可以使用File类的getAbsolutePath()方法获取文件或目录的绝对路径。该路径是一个字符串,表示文件或目录在文件系统中的位置。7、获取文件或目录的名称:可以使用File类的getName()方法获取文件或目录的名称。例如,如果文件位于C:\\Users\\username\\Documents\\file.txt,则文件名将是file.txt。8、创建文件夹:可以使用 mkdir() 或 mkdirs() 方法创建文件夹。 mkdir() 只创建最后一个不存在的父目录,而 mkdirs() 会创建所有不存在的父目录。9、判断是否是文件:可以使用 isFile() 方法判断路径是否对应一个普通文件。如果是,返回 true;否则返回 false。10、判断是否是目录:可以使用 isDirectory() 方法判断路径是否对应一个目录。如果是,返回 true;否则返回 false。11、其他操作:File类还提供了一些其他的方法,如listFiles()方法返回一个包含指定目录下所有文件的数组,list()方法返回一个包含指定目录下所有文件和子目录的字符串数组等。
File类的主要功能包括:
需要注意的是,如果某个文件夹需要权限才能访问,那么使用File类的listFiles方法返回的是null,为了代码不出现错误,我们需要对此进行判断。
public static void main(String[] args) { out_data(new File(\"E:\\\\简历\")); }public static void out_data(File f){ //获取文件名或文件夹名 System.out.println(\"--------------\"+f.getName()+\"------------------\"); File[] files = f.listFiles(); if(files == null) { return; } for(File ft : files){ // 判断是否文件夹,是则继续往下递归 if(ft.isDirectory()) { out_data(ft); } // 不是文件夹,则输出信息 else{ System.out.println(ft.getName()); } } System.out.println(\"--------------\"+f.getName()+\"------------------\");}
示例:输出某一文件夹中所有的文件信息(包括子文件夹):
File类
Java中的文件输入输出流是用于读取和写入文件的类。Java提供了两种类型的文件输入输出流:字节输入输出流和字符输入输出流。二者的区别在于,字节流是以字节为单位进行读取,随读随取,可以读取除文本外任意文件;字符流也是以字节进行读取,但是不同点在于它遇到中文时会按中文的编码方式进行读取,而带有缓冲区机制。
1、FileInputStream:用于从文件中读取字节数据。2、FileOutputStream:用于向文件中写入字节数据。3、BufferedInputStream:用于从文件中读取数据,并将数据缓存在内存中,以提高读取效率。4、BufferedOutputStream:用于向文件中写入数据,并将数据缓存在内存中,以提高写入效率。5、DataInputStream:用于从文件中读取基本数据类型,如int、float、double等。6、DataOutputStream:用于向文件中写入基本数据类型,如int、float、double等。
字节输入输出流以字节为单位进行读写操作。Java中提供了以下几种字节输入输出流类:
1、创建输入输出流对象:使用上述类之一的构造函数创建输入输出流对象。例如,使用FileInputStream类创建文件输入流对象,使用FileOutputStream类创建文件输出流对象。2、打开连接:使用open()方法打开文件,建立与文件的连接。3、读取/写入数据:使用输入输出流提供的方法读取或写入数据。例如,使用read()方法从输入流中读取字节数据,使用write()方法向输出流中写入字节数据。4、关闭连接:使用close()方法关闭文件,断开与文件的连接。
使用字节输入输出流进行文件读写的一般步骤如下:
import java.io.FileInputStream; import java.io.IOException; public class FileReadingExample { public static void main(String[] args) { try (FileInputStream fileInputStream = new FileInputStream(\"path/to/file.txt\")) { int data; while ((data = fileInputStream.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } } }
示例:读取文件
import java.io.FileOutputStream; import java.io.IOException; public class FileWritingExample { public static void main(String[] args) { try (FileOutputStream fileOutputStream = new FileOutputStream(\"path/to/file.txt\")) { String data = \
示例:写入文件
字节输入输出流
字符输入输出流以字符为单位进行读写操作。
FileReader:用于从文件中读取字符数据。FileWriter:用于向文件中写入字符数据。BufferedReader:用于从文件中读取数据,并将数据缓存在内存中,以提高读取效率。BufferedWriter:用于向文件中写入数据,并将数据缓存在内存中,以提高写入效率。BufferedWriter:用于向文件中写入数据,并将数据缓存在内存中,以提高写入效率。
Java中提供了以下几种字符输入输出流类:
1、创建输入输出流对象:使用上述类之一的构造函数创建输入输出流对象。例如,使用FileReader类创建文件输入流对象,使用FileWriter类创建文件输出流对象。2、打开连接:使用open()方法打开文件,建立与文件的连接。3、读取/写入数据:使用输入输出流提供的方法读取或写入数据。例如,使用read()方法从输入流中读取字符数据,使用write()方法向输出流中写入字符数据。4、关闭连接:使用close()方法关闭文件,断开与文件的连接。
使用字符输入输出流进行文件读写的一般步骤如下:
import java.io.FileReader; import java.io.IOException; public class FileReadingExample { public static void main(String[] args) { try (FileReader fileReader = new FileReader(\"path/to/file.txt\")) { int data; while ((data = fileReader.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } } }
import java.io.FileWriter; import java.io.IOException; public class FileWritingExample { public static void main(String[] args) { try (FileWriter fileWriter = new FileWriter(\"path/to/file.txt\")) { String data = \
需要注意的是,在进行io读取操作时,应该遵循“打开-使用-关闭”的原则,及时关闭连接以释放资源。同时,应该根据实际需求选择合适的流类,以达到最佳的读写效果。
字符输入输出流
文件输入 / 输出流
I/O(输入/输出)
反射,从字面意思的理解就是反过来映射,它的功能也是如此,一般我们要在程序的运行过程中获取一个类的内部信息,那么得先生成一个这个类的对象,然后再使用这个类对外提供的方法来获取,这个类对外提供了什么样方法我们就只能获得到什么信息。
在程序的过程中我们无法像直接翻看源代码一样查看到某个类的信息,但是通过反射机制,能让我们在程序运行阶段就能直接获取某个类中的所有信息,就算这个类的信息有些不对外开发,但是我们依然能获取到。
class类是一个特殊的类,Class类表示正在运行的Java应用程序中的类和接口。一个类在被JVM加载后,会在内存中生成对应Class对象,而我们可以通过获取对应类的Class对象,来获取这个类的信息。
Class类对象只有三种可以获取方式,因为Class中的构造方法被private修饰了,所以我们无法通过构造方法来创建Class类的对象。
获取方式
通过这个静态方法我们可以获取某个类的Class对象,全类名指的是这个类在什么位置。
例如:创建test包下的student类的Class对象。
public class demo_1 { public static void main(String[] args) throws ClassNotFoundException { Class claz = Class.forName(\"test.student\"); }}
1、Class.forName(“全类名”)
Class studentClass = student.class;
2、类名.class
Object类是所有类的父类,在Object类中有一个方法:getClass方法,这个方法可以获取一个对应的Class对象。所以我们可以使用这个方法获取。
3、对象.getClass()
class类
针对不同的需求可以使用不同的方法。
访问构造方法访问成员变量访问成员方法
Class类提供了很多的方法供我们使用,总得来说常用功能可以分为三大类:
1、Constructor[] getConstructors():获取所有公共(public)构造方法。2、Constructor[] getDeclaredConstructors():获取所有声明的构造方法,包括公共和非公共的。3、Constructor getConstructor(Class<?>… parameterTypes):获取具有指定参数类型的公共构造方法。4、Constructor getDeclaredConstructor(Class<?>… parameterTypes):获取具有指定参数类型的声明的构造方法,包括公共和非公共的。
需要注意的是,如果获取指定的构造方法,那么需要根据该构造方法来进行传参。
获取构造方法的常用方法
首先创建一个student进行示例说明,该类中拥有两个属性与多个构造方法,分别使用不同的权限修饰符进行修饰。
然后我们使用不同的获取方法进行获取这个类的构造方法。
结果
示例
1、访问构造方法
访问成员变量是使用Field类来进行的。
Field getField(Object obj):获取指定对象的成员变量。Field[] getFields():获取该类的所有公共(public)成员变量。Field[] getDeclaredFields():获取该类的所有成员变量,包括公共和非公共的。Field getDeclaredField(String name):获取具有指定名称的成员变量,包括公共和非公共的。
获取成员变量的常用方法:
FIeld类中常用方法对获取出来的成员变量进行操作的话,需要使用Field类,以下是常用的方法,具体详见Java1.8api文档。
首先创建一个studen类用于演示
获取成员变量
2、访问成员变量
访问某个类的成员方法是使用Method对象来进行操作的。
常用的方法有下图所示,具体详见Java1.8Api文档
获取Method对象常用的方法有:
给student类创建几个成员方法用于演示。
需要注意的是,如果使用getMethods方法来获取成员方法,那么它会返回本类的公共成员方法,也会返回从父类继承的成员方法。而使用getDeclaredMethods方法来获取的话,那么就不会返回父类的方法。
获取成员方法
执行结果
示例:
3、访问成员方法
常用功能
反射
在Java中,注解(Annotation)是一种特殊的注释,它提供了一种元数据机制,可以用于描述代码中的信息和元数据。注解是Java 5.0引入的一个新特性,它提供了一种将信息嵌入到Java代码中的方法,并且可以在编译时、运行时和代码生成时使用。
注解的作用域可以是类、方法、变量、参数等。例如,可以使用注解标记类、方法、变量等。
@MyAnnotation(name=\"example\
注解可以具有参数,参数可以是常量、字符串、整数等类型。例如:
注解可以被继承,子类可以继承父类中的注解。
@Override // 这是一个注解,表示覆盖从父类继承的方法public void myMethod() { // method body }
注解的基本语法很简单,它使用 @符号来标识,后面跟着注解的名称和参数。例如:
语法:
提供文档信息:注解可以用于描述代码中的方法和变量,提供可读性更好的文档信息。跟踪代码依赖性:注解可以用于标记代码中的依赖关系,方便跟踪和管理代码的依赖性。实现AOP(面向切面编程):通过注解定义切面行为,实现非侵入式增强。替代配置文件:注解可以用于简化配置和注入依赖关系的管理,减少配置文件的数量。编译时检查:某些注解可以用于检查代码中的格式或参数,例如@Override注解用于检查方法是否覆盖了超类方法。
用处:
1、预定义注解:包括常见的注解,如@Override、@Deprecated和@SuppressWarning等。这些注解通常用于标记代码中的特定元素,以便编译器在编译时进行警告或错误检查。2、元注解:元注解是用于注解其他注解的注解,包括@Target、@Retention和@Inherited等。这些注解主要用于定义注解的元数据,例如注解的应用范围、注解的生命周期以及注解的继承方式等。3、自定义注解:用户可以根据自己的需求定义注解。自定义注解可以根据需要添加参数和属性,以便更灵活地描述代码中的信息。
合理的使用注解可以在编译时进行检查,确保代码符合特定的规范或要求。但是同样注解也会增加代码的复杂度,使代码难以理解。注解有好处也有坏处,因此需要合理的使用注解。
注解的分类:
目前来看反射貌似没什么作用,但是在后序的学习中,反射还是很重要的,需要掌握好这个机制。
注解
反射与注解
本文主要讲述的是如何使用JDBC技术连接本地的数据库,编写Java语言代码来对本地的MySQL数据库进行基础的增删改查操作,所以阅读本文章之前还得对数据库的操作有基本的了解,望周知。
前言
JDBC(Java Database Connectivity)是Java中用于连接和执行SQL语句来与数据库进行交互的一种技术。 JDBC API包含了多种接口和类,允许Java程序与数据库进行通信。
你需要将MySQL的JDBC驱动包含在你的项目中。一般来说,这可以通过将相关的jar文件添加到项目的类路径中来完成。这个jar文件通常被称为mysql-connector-java-version-bin.jar,其中“version”是你的JDBC驱动的版本号。
在你的Java代码中,你需要在文件的顶部导入相关的包。这些包包括java.sql包和MySQL的JDBC驱动包。
import java.sql.*; import com.mysql.jdbc.*;
1、导入JDBC包
接下来,你需要创建一个连接到你的MySQL数据库的连接对象。这需要你的数据库的URL,用户名和密码。下面是一个例子:
String url = \"jdbc:mysql://localhost:3306/mydatabase\"; String user = \"root\"; String password = \"mypassword\
在上面的例子中,“localhost:3306”是你的MySQL服务器的地址和端口(通常为3306),“mydatabase”是你的数据库名,“root”和“mypassword”是你的用户名和密码。
2、建立连接
一但设置了连接对象,你就可以创建一个Statement对象,然后使用它来执行SQL查询
Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(\"SELECT * FROM mytable\");
在上面这个例子中,“mytable”是你的表名。执行查询后,你将得到一个ResultSet对象,你可以使用它来获取查询的结果。
3、创建语句和执行查询
while(rs.next()) { String column1 = rs.getString(\"column1\"); int column2 = rs.getInt(\"column2\"); //...处理结果... } rs.close(); // 关闭ResultSet stmt.close(); // 关闭Statement conn.close(); // 关闭Connection
在执行查询后,你需要处理查询的结果,并且清理你的资源。下面是一个例子:
在这个例子中,你需要替换\"column1\"和\"column2\"等为你的列的名字。在处理完结果后,你需要关闭ResultSet、Statement和Connection对象。这可以确保你的资源被正确地清理,防止内存泄漏和其他问题。
4、处理结果和清理资源
使用JDBC技术连接MySQL数据库的步骤:
JDBC技术
1、DriverManager类:用于加载和管理JDBC驱动程序。DriverManager类提供了一个静态方法getConnection(),它返回一个Connection对象,该对象表示与数据库的连接。2、Connection接口:代表与数据库的连接。Connection接口提供了一些方法来创建Statement、PreparedStatement和CallableStatement等对象,用于执行SQL语句和存储过程等。3、Statement接口:用于执行静态SQL语句并返回ResultSet对象。可以使用Statement接口的executeQuery()方法执行查询,返回ResultSet对象表示查询结果集;使用executeUpdate()方法执行更新操作,返回一个int值表示受影响的行数。4、PreparedStatement接口:用于执行动态SQL语句。PreparedStatement接口继承了Statement接口,并提供了额外的setXXX()方法来设置SQL语句中的参数。使用PreparedStatement接口可以提高性能和安全性。5、ResultSet接口:用于获取查询结果集中的数据。ResultSet接口提供了一些方法来获取列值、列名等。6、CallableStatement接口:用于调用存储过程。CallableStatement接口继承了PreparedStatement接口,并提供了一些方法来设置存储过程的参数和获取返回值。7、Driver接口:JDBC驱动程序必须实现的接口。Driver接口定义了一些标准方法,如connect()、getMajorVersion()和getMinorVersion()等,用于与DriverManager进行通信。8、SQLException异常类:在JDBC操作中可能会抛出SQLException异常类,表示发生了某种数据库访问错误。
JDBC中常用的类和接口
String driver=\"com.mysql.cj.jdbc.Driver\"; // 驱动类Driver在jar包中位置String url=\"jdbc:mysql://localhost:3306/需要连接的数据库名\";/** 它的值是\"jdbc:mysql://localhost:3306/javasql\",这通常是一个连接到MySQL数据库的JDBC(Java Database Connectivity)URL。这个URL指定了如何连接到位于本地主机(localhost)的MySQL数据库服务器(端口号为3306),以及要连接到的数据库名称为'javasql'。* */String user=\"数据库用户名\"; // 用户名String password=\"数据库密码\
1.连接数据库:
下面这个例子中代码会连接到一个名为\"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对象,其余并无差距,这里就只举例新增操作。
import java.sql.*; public class Main { public static void main(String[] args) { // ...(省略连接部分的代码) try { // 创建一个PreparedStatement对象 PreparedStatement pstmt = conn.prepareStatement(\
增、删、改操作
上面代码将创建一个新的用户记录。注意,\"?\"符号在SQL语句中代表一个通配符,我们在set()方法中为这些参数设置值,通配符顺序从1开始计算,且代表不同参数的通配符需要使用不同的set方法来设置值。执行executeUpdate()方法会将这条SQL语句发送到数据库,创建一个新的用户记录。
数据库操作
Swing是Java平台的一部分,它是一个用于开发Java应用程序用户界面的开发工具包。
Swing的主要目的是提供一个跨平台的用户界面工具包,让开发人员能够轻松地创建具有丰富用户界面的应用程序,并且这些应用程序可以在不同的操作系统上运行。Swing是基于Java AWT(抽象窗口工具包)构建的,通过提供一组跨平台的GUI组件和布局管理器来解决AWT主要问题的不跨平台。
Swing开发人员只用很少的代码就可以利用Swing丰富、灵活的功能和模块化组件来创建优雅的用户界面。
Swing概述
Swing是Java的一个图形用户界面(GUI)工具包,它提供了创建窗口、对话框、按钮等图形元素所需要的类。
1、JFrame:这是Swing中一个顶层窗口容器,可以用来创建窗口、对话框等。它包含了窗口的一些基本属性,如标题、大小、位置等。2、JDialog:这是Swing中的一个对话框容器,通常用于在用户需要输入一些信息或者做出一些选择时弹出。它也包含了对话框的一些属性,如标题、内容、大小等。3、JWindow:这是Swing中的一个无标题的顶级窗口容器,通常用于创建一些不需要标题的窗口。4、JInternalFrame:这是Swing中的一个内部窗口容器,通常用于在桌面应用程序中创建多个窗口,这些窗口可以像浏览器标签一样堆叠在一起。5、JFrame.JContentPane:这是Swing中的一个内容面板,它可以将组件放置在其上,并且可以包含滚动条、边框等。它通常用于创建一些需要放置多个组件的窗口。6、JScrollPane:这是Swing中的一个滚动面板,它可以包含另一个面板或者组件,并且可以在需要时显示滚动条。它通常用于创建一些需要显示大量内容的窗口。
以下时Swing中的常用窗体简介:
JFrame是Java Swing库中的一个顶层窗口容器,它提供了创建窗口的基本功能,是Swing应用程序中创建窗口的基类。
1、JFrame是一个顶级窗口,必须添加内容才能显示窗口。2、JFrame可以添加各种组件,如按钮、文本框、标签等。3、JFrame具有默认的关闭操作,可以关闭窗口。4、JFrame可以设置窗口大小、标题等属性。
JFrame具有以下特点:
JFrame的主要方法包括:
public class Main { public static void main(String[] args) { JFrame jf = new JFrame(\"第一个窗体\
1、JFrame窗体
JDialog是Java Swing库中的一个对话框窗体,它继承了AWT组件中的java.awt.Dialog类。JDialog窗体的功能是从一个窗体中弹出另一个窗体,类似于在使用IE浏览器时弹出的确定对话框。
JDialog窗体与JFrame窗体类似,它们都是顶层窗口容器,但是JDialog窗体通常用于创建模态对话框,可以与用户进行交互并获取用户输入。
1、可以创建模式对话框和非模式对话框。模式对话框会阻塞用户对其他窗口的访问,直到用户关闭该对话框或通过操作按钮取消对话框。非模式对话框不会阻塞用户对其他窗口的访问。2、可以添加各种组件,如按钮、文本框、标签等。3、可以设置对话框的标题、大小、位置等属性。4、对话框默认情况下没有关闭操作,需要手动添加关闭操作。
JDialog窗体具有以下特点:
JDialog的主要方法包括:
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class DialogExample { private JFrame frame; private JButton button; private JDialog dialog; private JTextField textField; public DialogExample() { // 创建主窗口 frame = new JFrame(\"Dialog Example\
在以上示例中,我们创建了一个主窗口(JFrame),并在其中添加了一个按钮(JButton)。当用户点击按钮时,会弹出一个模态对话框(JDialog),其中包含一个文本框(JTextField)。用户可以在文本框中输入内容,然后关闭对话框。在关闭对话框后,用户可以继续操作主窗口。
2、JDialog对话框
JOptionPane是Java Swing库中的一个用于显示对话框的类。它提供了一些方便的方法来创建各种类型的对话框,例如确认对话框、输入对话框、消息对话框等。
JOptionPane的主要方法包括:
import javax.swing.*; import java.awt.*; public class OptionPaneExample { public static void main(String[] args) { // 创建JFrame窗口 JFrame frame = new JFrame(\"OptionPane Example\
在以上示例中,我们创建了一个JFrame窗口,并在其中添加了一个按钮。当用户点击按钮时,会弹出一个包含\"Hello World!\"消息的消息对话框。
3、JOptionPane小型对话框
Swing常用窗体
在Java的Swing库中,布局管理器是一种用于自动调整组件位置和大小的机制。它们使得开发人员可以创建复杂的用户界面,而无需手动计算每个组件的位置和大小。
1、BorderLayout:这是默认的布局管理器,它将容器分为5个区域:北(NORTH)、南(SOUTH)、东(EAST)、西(WEST)和中(CENTER。你可以将组件添加到这些区域中。注意,每个区域只能包含一个组件。2、FlowLayout:此布局管理器将组件按照水平或垂直方向排列。如果容器宽度或高度不足以容纳所有的组件,那么会换行或换列。3、GridLayout:此布局管理器将容器分为行和列,形成网格。你可以指定行数和列数,然后添加组件到网格的特定位置。4、CardLayout:此布局管理器用于显示一个组件集合中的某一个组件。当用户切换卡时,显示不同的组件。例如,你可以使用它来在多个用户界面之间切5、GridBagLayout:这是一个更复杂的布局管理器,允许组件占据多个行或列的空间。你可以设置组件的位置、大小、填充方式、对齐方式等。6、BoxLayout:此布局管理器将组件在一行或一列中布局,可以指定组件的对齐方式。7、SpringLayout:此布局管理器允许组件在网格中的位置和大小由周围的组件决定,就像弹簧一样。通常与其他布局管理器(如GridLayout)结合使用。8、BorderLayoutManager:这是Java 11中新增的布局管理器,它实现了BorderLayout,但添加了一些额外的功能。例如,它可以处理组件的溢出,当组件的大小超过其容器的大小时,会显示一个滚动条。
以上布局管理器各有优缺点,使用哪个取决于你的具体需求。
以下是Java中常用的几种布局管理器:
Java中的null绝对布局是一种特殊的布局方式,它没有特定的布局管理器类来表示,而是通过设置组件的坐标和宽高来布置组件。在这种布局方式下,开发人员需要明确指定每个组件的坐标和宽高,否则组件将无法显示。使用其他布局时,如果在窗口显示之后添加新组件,该组件也需要手动指定坐标和宽高。同样,如果在窗口显示之后修改之前添加的组件的坐标和宽高,该组件也会被当做绝对布局对待,此时修改坐标和宽高会生效。
效果:
import javax.swing.*;import java.awt.*;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class Main { public static void main(String[] args) { JFrame frame = new JFrame(\"Null Layout Example\
1、null绝对布局
Java中的FlowLayout流布局管理器是一种简单的布局管理器,它将组件按照水平或垂直方向排列。在FlowLayout中,组件的排列顺序取决于容器的组件添加顺序。
FlowLayout有两个主要的属性:hgap和vgap。hgap属性用于设置水平方向上两个组件之间的间距,vgap属性用于设置垂直方向上两个组件之间的间距。
在FlowLayout中,每个组件的位置是由其添加的顺序决定的。如果容器宽度不足以容纳所有组件,那么会换行或换列,以便容纳所有的组件。
如果容器高度不足以容纳所有组件,那么会根据组件的尺寸和排列顺序来决定是否换行或换列。
import javax.swing.*;import java.awt.*;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class Main { public static void main(String[] args) { JFrame frame = new JFrame(\"FlowLayout Example\
2、FlowLayout流 布局管理器
Java中的BorderLayout边界布局管理器是一种常见的布局管理器,它将容器分为5个区域:北(NORTH)、南(SOUTH)、东(EAST)、西(WEST)和中(CENTER)。 你可以将组件添加到这些区域中。
使用BorderLayout布局管理器时,每个区域只能包含一个组件。如果尝试将多个组件添加到同一个区域,则只有最后一个组件会显示在该区域中。
1、每个区域只能包含一个组件。2、组件不能覆盖多个区域。3、组件的添加顺序不重要。4、组件的尺寸由其自身的大小和容器的大小决定。5、可以使用组件的setBounds方法设置组件的位置和大小。
以下是BorderLayout布局管理器的特点:
import javax.swing.*;import java.awt.*;public class Main { public static void main(String[] args) { JFrame frame = new JFrame(\"BorderLayout Example\
3、BorderLayout 边界 布局管理器
GridLayout 网格布局管理器能够把容器划分为网格,组件可以按行列进行排列。
在网格布局管理器中,网格的个数由行数和列数决定,且每个网格的大小都相同。从网格的左上角开始,按照从左到右,从上到下的顺序被添加到网格中,且每个组件都会填满整个网格。改变窗口大小的同时,组件的大小也会随之改变
网格布局管理器主要有以下两个常用的构造方法:
rows和columns这两个参数只允许有一个参数可以为零,被用于表示一行或一列可以排列任意多个组件
效果图
4、GridLayout 网格布局管理器
常用布局管理器
在Swing程序设计中,面板是一个容器,被用于容纳其他组件,但面板必须被添加到其他容器中。Swing中常用的面板包括JPanel面板和JScrollpane面板JPanel面板继承Java.awt.Container类,JPanel面板必须在窗体容器中使用,无法脱离窗体显示
运行效果:
JScrollPane面板,是带滚动条的面板,被用于在较小的窗体中显示较大篇幅的内容,要注意的是,不能使用布局管理器,只能容纳一个组件,如果添加多个组件,那么需要先将多个组件添加到JPanel面板,再将JPanel面板添加到滚动面板
JScrollPane滚动面板
常用面板
标签被用于显示文本,图标等内容。用户能够通过标签上的文本图标等内容获取相应的提示信息。
JLabrl标签的父类是JComponent类,标签不能被添加监听器,但是标签显示的文本,图标等内容可以指定对齐方式,通过JLabrl类的构造方法可以创建多种标签,常用的构造方法如下:
import javax.swing.*;import java.awt.*;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class Main extends JFrame { public Main(){ Container container=getContentPane();//获取主容器 JLabel jl=new JLabel(\"这是一个 JFrame 窗体\
1、JLabrl标签
在swing程序设计中,图标经常被添加到标签,按钮等组件它有多个常用方法如下:
import javax.swing.*;import java.awt.*;import java.net.URL;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class Main extends JFrame { public Main(){ Container container=getContentPane(); JLabel jl=new JLabel(\"这是一个JFrame窗体\");//创建标签 URL url=Main.class.getResource(\"img\\cell.png\
2、图标的使用
文字标签组件与图标
在Swing程序设计中,按钮是较为常见的组件,被用于触发特定的动作提供了多种按钮,组件按钮,单选按钮,复选框等
Swing按钮由JButto对象表示。
JButto常用的构造方法如下:
1、setText(String text):设置按钮上显示的文本。2、setMnemonic(char mnemonic):设置按钮的快捷键。3、setActionListener(ActionListener listener):设置按钮的监听器,当按钮被点击时触发。4、setBackground(Color color):设置按钮的背景色。5、setForeground(Color color):设置按钮上显示的文本的颜色。6、setFont(Font font):设置按钮上显示的文本的字体。7、setBorder(Border border):设置按钮的边框。8、setRolloverIcon(Icon icon):设置按钮在鼠标指针滑过时显示的图标。9、setDisabledIcon(Icon icon):设置按钮被禁用时显示的图标。10、setDisabledSelectedIcon(Icon icon):设置按钮被禁用且被选中时显示的图标。
创建JButto对象后如果要JButto对象进行设置,那么可以使用JButto提供的方法,提供的方法如下表所示:
import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.net.URL;public class Main extends JFrame { public Main(){ Icon icon=new ImageIcon(\"\
1、JButto按钮
Swing单选按钮由JRadioButton对象表示,在swing程序设计中,需要把多个单选按钮添加到按钮组,当用户选中某个单选按钮时,按钮组中的其他单选按钮将不能被同时选中
import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.net.URL;public class Main extends JFrame { public Main(){ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setTitle(\"单选按钮的使用\
2、JRadioButton单选按钮
复选框组件由JCheckBox对象表示,以单选按钮不同的是,窗体中的复选框可以被选中多个,这是因为每一个复选框都提供了被选中和不被选中两种状态。
常用构造方法如下:
3、JCheckBox复选框
按钮组件
Swing中提供两种列表组件,分别为下拉列表框(JComboBox)和列表框(JList),下拉列表框与列表框都是带有一系列列表选项的组件,用户可以从中选择需要的列表项,列表框较下拉列表框更直观,他们将所有的列表项罗列在列表框,但是下拉列表这个表框更为便捷美观,它将所有的列表项隐藏起来,当用户用其中的列表项时才会显示出来
初次使用下拉列表框时,会感觉swing中的下拉列表框以WINDOWS操作系统中的下拉列表框有一些相似,实质上两者并不完全相同,因为swing中的下拉列表框不仅可以供用户从中选择,列表项也提供编辑列表项的功能。
JComboBox类的常用构造方法如下:
常用方法:
import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.net.URL;public class Main extends JFrame { public Main(){ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setTitle(\"下拉列表框的使用\
1、JComboBox下拉列表框
列表框组件被添加到窗体中后,就会被指定长和宽。如果列表框的大小不足以容纳列表项的个数,那么需要设置列表框具有滚动效果,即把列表框添加到滚动面板
列表框组件由j list对象表示常用构造方法如下:
import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.net.URL;public class Main extends JFrame { public Main(){ Container cp=getContentPane();//获取窗体主容器 cp.setLayout(null);//容器使用绝对布局 //创建字符串数组保存列表中的数据 String[]contents= {\"列表1\
2、JList列表框
列表组件
文本组件在开发swing程序过程中经常被用到,尤其是文本框组件和密码框组件。
文本框组件由JTextField对象表示。
JTextField常用构造方法如下:
import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.net.URL;public class Main extends JFrame { public Main() { Container c = getContentPane();//获取窗体主容器 c.setLayout(new FlowLayout()); JTextField jt = new JTextField(\"请点击清除按钮\");//设定文本框初始值 jt.setColumns(20);//设置文本框长度 jt.setFont(new Font(\"宋体\
1、JTextField文本框
密码框组件由JPasswordField对象表示,其作用是把用户输入的字符串,以某种符号进行加密。
常用构造方法如下:
2、JPasswordField密码框
文本域组件由JTextArea对象表示,其作用是接受用户的多行文本输入。
JTrxtArea类提供了一个setLineWrap(boolean wrap)方法,这个方法被用于设置文本域中的文本内容,是否可以自动换行。如果参数为true,那么会自动换行,否则不会自动换行此外,还提供了一个append(String str)方法,这个方法被用于向文本域中添加文本内容。
3、 JTextArea文本域
文本组件
Swing表格由JTable表示其作用是把数据以表格的形式显示给用户。
JTanle类除了提供了默认的构造方法外,还提供了被用于显示二维数组中的元素的构造方法。这个构造方法的语法如下:
JTanle(Object[][]rowDate,Object[]columnNames)rowDate存储表格数据的二维数组columnNames,存储表格列明的一维数组
**在使用表格时,要先把表格添加到滚动面板,再把滚动面板添加到窗体的相应位置 **
import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.net.URL;public class Main extends JFrame { public Main() { setTitle(\"创建可以滚动的表格\
1、创建表格
Swing使用TableModel接口定义了一个表格模型,AbstractDefaultTableModel抽象类实现了TableModel接口的大部分方法。
只有以下三个抽象方法没有实现:
为了实现使用表格模型,创建表格的功能swing提供了表格模型类,DefaultTableModel,DefaultTableModel常用构造方法如下:
import javax.swing.*;import javax.swing.table.DefaultTableModel;import javax.swing.table.TableRowSorter;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.net.URL;public class Main extends JFrame { public Main() { setTitle (\"表演模型与表格\
2、DefaultTableModel表格数据模型
表格中的数据内容需要用于维护。
使用getValueAt()方法获得表格中某一个单元格的值,使用addRow()方法向表格中添加新的行使用setValueAt方法修改表格中某一个单元格的值使用removeRow方法从表格中删除指定行等
当删除表格模型中的指定行时,每删除一行,其后所有行的索引值将相应的减一,所以当连续删除多行时,需要注意对删除行索引的处理。
import javax.swing.*;import javax.swing.table.DefaultTableModel;import javax.swing.table.TableRowSorter;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.MouseAdapter;import java.awt.event.MouseEvent;import java.net.URL;public class Main extends JFrame { private DefaultTableModel tableModel;//定义表格模型对象 private JTable table;//定义表格对象 private JTextField aTextFied; private JTextField bTextFied; public Main() { setTitle(\"维护表格模型\
3、维护表格模型
表格组件
Java中的事件监听器是一种用于监听特定事件并对其做出响应的机制。它由事件类和监听接口组成,当特定事件发生时,事件源会调用相应的监听器接口的方法,并在调用时将事件对象传递进去。
事件类是继承自java.util.EventObject的类 用于表示事件本身的属性和状态。例如,ActionEvent类表示用户界面组件的动作事件。
监听接口是继承自java.util.EventListener的类,它定义了事件发生时应执行的操作。例如,ActionListener接口定义了actionPerformed方法,当按钮被点击时,该方法会被调用。
使用事件监听器可以方便地实现对特定事件的管理和响应。
在Java中,事件监听器是通过将事件对象传递给监听器接口的方法来实现的。通过在方法中访问事件对象,可以获取有关事件的信息,例如事件源和事件类型,从而对事件进行适当的处理。
在Java中,ActionEvent是用于监听用户界面(UI)组件(如按钮点击,菜单项选择等)的动作事件的一种事件。ActionEvent类是java.awt.event包的一部分,它包含有关发生的事件的信息,例如事件源,发生事件的时间以及事件的类型。当用户执行某种动作(如点击按钮)时,相应的组件会生成一个ActionEvent对象,然后调用其监听器的actionPerformed方法。这个方法是在ActionListener接口中定义的。
import javax.swing.*;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;public class Main extends JFrame { private JButton jb=new JButton(\"我是按钮,点击我\
1、ActionEvent动作事件
在Java中,KeyEvent是用于捕获键盘事件的一个类。
当向文本框中输入内容时,会发出键盘事件。KeyEvent类负责捕获这些键盘事件,并且可以通过为组件添加实现了KeyListener接口的监听器类来处理相应的键盘事件。
KeyListener接口定义了三个抽象方法,它们分别在发生击键事件、按键被按下和释放时被触发。具体地,当按下一个键时会调用KeyPressed处理器,当松开一个键时会调用KeyReleased处理器,当输入一个统一编码时会调用KeyTyped处理器。
1、public void keyTyped(KeyEvent e):发生击键事件时被触发2、public void keyPressed(KeyEvent e):按键被按下时被触发3、public void keyReleased(KeyEvent e):按键被释放时被触发
KeyListener接口的这些方法可以在用户执行键盘操作时被调用,从而实现对键盘事件的处理。例如,当用户按下键盘上的一个键时,相应的KeyPressed方法就会被调用,这个方法中可以编写处理按键按下的代码。在Java的Swing库中,很多组件(如JTextField等)都提供了添加KeyListener的方法,使得这些组件在用户执行键盘操作时能够触发事件。例如,JTextField提供了addKeyListener方法来添加一个KeyListener。
KeyListener常用方法:
import java.awt.BorderLayout;import java.awt.EventQueue;import javax.swing.JFrame;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import java.awt.Color;import java.awt.Component;import javax.swing.JButton;import java.awt.Font;import javax.swing.SwingConstants;import javax.swing.border.TitledBorder;import java.awt.event.KeyAdapter;import java.awt.event.KeyEvent;import java.util.ArrayList;import javax.swing.JTextField;/** * 虚拟键盘(键盘的按下与释放) */public class Main extends JFrame { // 创建“键盘”类继承JFrame // 声明窗体中的成员组件 private JPanel contentPane; private JTextField textField; private JButton btnQ; private JButton btnW; private JButton btnE; private JButton btnR; private JButton btnT; private JButton btnY; private JButton btnU; private JButton btnI; private JButton btnO; private JButton btnP; private JButton btnA; private JButton btnS; private JButton btnD; private JButton btnF; private JButton btnG; private JButton btnH; private JButton btnJ; private JButton btnK; private JButton btnL; private JButton btnZ; private JButton btnX; private JButton btnC; private JButton btnV; private JButton btnB; private JButton btnN; private JButton btnM; Color green = Color.GREEN;// 定义Color对象,用来表示按下键的颜色 Color white = Color.WHITE;// 定义Color对象,用来表示释放键的颜色 Color red=Color.RED; ArrayList<JButton> btns = new ArrayList<JButton>();// 定义一个集合,用来存储所有的按键ID // 自定义一个方法,用来将容器中的所有JButton组件添加到集合中 private void addButtons() { for (Component cmp : contentPane.getComponents()) {// 遍历面板中的所有组件 if (cmp instanceof JButton) {// 判断组件的类型是否为JButton类型 btns.add((JButton) cmp);// 将JButton组件添加到集合中 } } } /** * 主方法 */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { // 使得Runnable中的的run()方法在the system EventQueue的指派线程中被调用 public void run() { try { Main frame = new Main(); // 创建KeyBoard对象 frame.setVisible(true); // 使frame可视 frame.addButtons();// 初始化存储所有按键的集合 } catch (Exception e) { e.printStackTrace(); } } }); } /** * 创建JFrame窗体 */ public Main() { // KeyBoard的构造方法 setTitle(\"\\u865A\\u62DF\\u952E\\u76D8\\uFF08\\u6A21\\u62DF\\u952E\\u76D8\\u7684\\u6309\\u4E0B\\u4E0E\\u91CA\\u653E\\uFF09\
2、KeyEvent键盘事件监听器
所有组件都能发生鼠标事件,MouseEvent类负责捕捉鼠标事件,可以通过为组件添加实现了MouseListener接口的监听器类来处理相应的鼠标事件
public void mouseEntered(MouseEvent e):光标移入组件时被触发public void mousePressed(MouseEvent e):鼠标按键被按下时被触发public void mouseReleased(MouseEvent e):鼠标按键被释放时被触发public void mouseClicked(MouseEvent e):发生单机事件时被触发public void mouseExited(MouseEvent e):光标移出组件时被触发
MouseListener接口有5个抽象方法:
分别代表:左键、滚轮和右键。
静态常量:
import javax.swing.*;import java.awt.*;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;public class Main extends JFrame { public static void main(String args[]) { Main frame = new Main(); frame.setVisible(true); // 设置窗体可见,默认为不可见 } /** * 判断按下的鼠标键,并输出相应提示 * * @param e 鼠标事件 */ private void mouseOper(MouseEvent e) { int i=e.getButton(); if(i==MouseEvent.BUTTON1) System.out.println(\"按下的是鼠标左键\"); else if (i==MouseEvent.BUTTON2) System.out.println(\"按下的是鼠标滚轮\"); else if(i==MouseEvent.BUTTON3) System.out.println(\"按下的是鼠标右键\"); } public Main() { super(); // 继承父类的构造方法 setTitle(\"鼠标事件示例\
3、MouseEvent鼠标事件
事件监听器
Swing程序设计
Java绘图是指在Java程序中创建和显示图形的过程。Java提供了许多类和方法来支持绘图。
Java中主要的绘图类是Graphics类,它提供了基本的绘图方法和属性设置方法。
Graphics类的一些常用方法:
Java中的Graphics2D类是Graphics类的扩展,提供了更高级的绘图功能和更灵活的绘图控制。Graphics2D类可以控制绘图颜色、线条粗细、填充方式等,并支持更复杂的图形绘制和渲染效果。
public class Mian{ public static void main(String[] args) { JFrame jf=new JFrame(\"wuhu\
Graphics2D类
Java绘图类
Java语言使用Color类封装颜色的各种颜色,并对颜色进行管理。另外,在绘制图形时还可以指定线的粗细和虚实等画笔属性。
使用Color类可以创建任意颜色的对象,不用担心平台是否支持该颜色,因为Java是以跨平台和与硬件无关的方式支持对颜色的管理。绘图类可以使用setColor()方法设置当前颜色。语法如下:
setColor(Color color); // 设置当前颜色
Color类提供了多个构造方法,以下为常用的构造方法。
Color类还提供了多个常量表示常用颜色。
设置颜色
默认情况下,Graphics类使用的画笔属性是粗细为1个像素的正方形,而Graphics2D类可以调用setStroke()方法设置画笔的属性,如改变线条的粗细、虚实,定义线段端点的形状,风格等。
setStroke(Stroke stroke);
格式如下:
设置画笔
setPaint(Paint p): 此方法用于设置画笔的刷子。参数p是一个Paint对象,表示所需的刷子。可以使用Color对象创建Paint对象。
设置笔刷
setStroke(Stroke s): 此方法用于设置画笔的线条粗细。参数s是一个Stroke对象,表示所需的线条样式。可以使用BasicStroke类创建不同的线条样式。
设置粗细
绘图颜色与画笔属性
在Java中,可以使用Graphics或Graphics2D类来绘制文本。这些类提供了许多方法来设置文本的字体、大小、颜色等属性,以及绘制文本的位置和内容
常用方法
绘制文本
在Java中,可以使用Graphics或Graphics2D类来显示图片。这些类提供了许多方法来加载图片、调整图片大小和位置、绘制图片等。
这些方法可以在Java Swing和Java AWT组件中使用,例如在JFrame、JPanel、JLabel等组件中显示图片。还可以使用其他类和方法来进一步控制图片的样式和布局,例如使用ImageObserver接口来观察图片的加载和绘制过程,使用AffineTransform类来对图片进行变换等。
package demo_1;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Image;import java.io.File;import java.io.IOException;import javax.imageio.ImageIO;import javax.swing.JFrame;import javax.swing.JPanel;public class text_1 extends JFrame{ Image img;//展示的图片 public text_1(){ try { img=ImageIO.read(new File(\"img/up.png\
显示图片
使用了 drawImage() 方法将图片以原始大小显示在窗体中,要想实现图片的放大与缩小,则需要使用他的重载方法。
1、放大与缩小
图像的翻转需要使用 drawImage() 方法的另一个重载方法。
此方法总是用来非缩放的图像来呈现缩放的矩形,并动态地执行所需要的缩放。此操作不使用缓存的缩放图像。执行图像从源到目标的缩放,要将源矩形的第一个坐标映射到目标矩形的第一个坐标,源矩形的第二个坐标映射到目标矩形的第二个坐标,按需要缩放和翻转子图像,以保持这些映射关系。
2、图像翻转
图像旋转需要调用 Graphics2D 类的 rotate()方法,该方法将根据指定的弧度旋转图像。
package demo_1;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Image;import java.io.File;import java.io.IOException;import javax.imageio.ImageIO;import javax.swing.JFrame;import javax.swing.JPanel;public class text_1 extends JFrame { private Image img; private text_1() { try { img=ImageIO.read(new File(\"img/right.png\
3、图像旋转
可以使用 Graphics2D 类提供的 shear()方法设置绘图的倾斜方向,从而使图像实现倾斜的效果。
package demo_1;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Image;import java.io.File;import java.io.IOException;import javax.imageio.ImageIO;import javax.swing.JFrame;import javax.swing.JPanel;public class text_1 extends JFrame{ private Image img; public text_1() { try { img=ImageIO.read(new File(\"img/cell.png\
4、图像倾斜
图像处理
Java绘图
Java是支持多线程的编程语言,所谓多线程就是程序能够同时完成多种操作。计算机完成可以多种操作同时进行,这种思想在Java中被称为并发,而将并发完成的多种操作被称为线程。
继承Thread类创建实现Runnable接口创建
在Java中线程的创建一般分为两种方式:
Java中的Thread类是java.lang包中的核心类,它代表一个线程。它主要用于创建新线程并在其中执行自定义任务。
1、继承性:Thread类是java.lang.Object的子类,因此可以继承Object类的属性和方法。2、抽象性:Thread类是一个抽象类,这意味着它不能直接实例化。为了使用Thread类,我们需要创建一个Thread的子类,并重写其run()方法。3、线程安全性:Thread类是线程安全的,这意味着多个线程可以同时调用Thread类的方法,而不会导致数据不一致或其他并发问题。4、常用方法:Thread类有许多有用的方法,包括start()(启动线程)、run()(执行线程)、sleep()(使线程休眠)、interrupt()(中断线程)等。
Thread类的主要特点包括:
public class MyThread extends Thread { @Override public void run() { // 在这里编写线程需要执行的代码 System.out.println(\"My thread is running.\"); } }
继承Thread类创建一个新的线程语法:
完成线程真正功能的代码放置在run方法中执行,该线程在执行完run方法中的代码后就会停止。
public class demo_1 { public static void main(String[] args) { /* 实现方式:1 自定义一个类继承Thread、或者构建Thread对象,重写run方法 重写run方法 启动线程 */ MyThread t1=new MyThread(); MyThread t2=new MyThread(); // 为线程指定名字 t1.setName(\"线程一\"); t2.setName(\"线程二\"); t1.start(); // 开启线程 t2.start(); // 开启线程 }}class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println(getName()+ \"芜湖\"); } }}
1、继承Thread类
上一种方式创建线程的方式,是通过继承Thread类的方式创建的,但是Java是只支持单继承的语言,所以如果通过上一个方式创建线程的话,拓展性不太好。因此就可以使用实现接口的方式来创建线程。
1、自定义一个类实现Runnable接口2、重写run方法,3、创建自己类的对象,4、创建Thread对象开启线程
实现过程:
package text_1;public class demo_2 { public static void main(String[] args) { /* * 第二种实现方式: * 自定义一个类实现Runnable接口 * 重写run方法, * 创建自己类的对象, * 创建Thread对象开启线程 * * */ MyRun mr=new MyRun(); Thread t1=new Thread(mr); Thread t2=new Thread(mr); t1.setName(\"芜湖\"); t2.setName(\"呀呼\"); t1.start(); t2.start(); }}class MyRun implements Runnable{ @Override public void run() { Thread thread = Thread.currentThread(); // 获取当前线程的对象 for (int i = 0; i < 10; i++) { System.out.println(thread.getName()+ \"爱坤\"); } }}
只所以能通过这中方式创建线程,是因为Thread类就是Runnable接口的实现类。
且在Thread类中的构造方法中有Runnable的实例,使用这种构造方法就可以将Runnable实例与Thread实例相关联,也就是说,使用这种构造方法后,Thread类调用的run方法就是Runnable中的run方法。
2、实现Runnable接口
线程的创建
线程的生命周期
操作线程的方法有很多,这些方法可以使得线程从某种状态过度到另一种状态。
sleep方法
该方法使得当前线程在指定的时代内不会进入就绪状态。该方法是被static修饰的,所以可以直接使用类名调用。
package text_2;public class demo_1 { public static void main(String[] args) { MyThread mt1 = new MyThread(); mt1.start(); }}class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 10; i++) { try { // 以毫秒为单位 Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(\"芜湖\"); } }}
1、线程的休眠
在Java多线程编程中,join方法是一个非常重要的概念。它用于确保主线程等待其他线程完成其任务后再继续执行。当一个线程调用另一个线程的join方法时,调用线程会阻塞,直到被调用线程结束执行。
join方法通常在创建线程时使用,以确保主线程不会在子线程完成前结束。这有助于防止数据竞争和其他并发问题。
package text_2;public class demo_1 { public static void main(String[] args) throws InterruptedException { MyThread mt1 = new MyThread(); MyThread mt2 = new MyThread(); mt1.setName(\"wuhu\"); mt2.setName(\"yahu\"); mt1.start(); mt1.join(); mt2.start(); }}class MyThread extends Thread{ @Override public void run() { for (int i = 0; i < 4; i++) { try { // 以毫秒为单位 Thread.sleep(10); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println(getName()); } }}
join方法
2、线程的加入
在Java中,线程礼让是指在线程A和线程B执行的时候,线程B由于某种原因需要先一步执行,那么可以对线程A执行yield方法,先让线程B执行一步。请注意,这里和join方法不一样,join方法是将CPU资源全都分出,直到线程B执行完,而yield只会让出一步。
3、线程的礼让
在Java中,线程的优先级是一个整数,范围从1(最低优先级)到10(最高优先级)。默认情况下,新创建的线程的优先级为5。线程优先级越小,线程越优先被执行;线程优先级越大,线程越后被执行。可以通过Thread类的setPriority(int)方法来设置线程的优先级。
请注意,如果优先级相同的线程同时存在,那么会按照提交顺序(也就是代码编写顺序)执行的方式。
package text_2;public class demo_2 { public static void main(String[] args) { /* * 设置优先级 :setPriority() * 获取优先级 : get * 守护线程 :setDaemon(boolean) * 细节:守护线程会在所有非守护线程结束后结束 * */// System.out.println(Thread.currentThread().getPriority()); MyThread_2 mt1 = new MyThread_2(); MyThread_2 mt2 = new MyThread_2(); mt1.setName(\"芜湖\"); mt2.setName(\"呀呼\"); System.out.println(mt1.getPriority()); // 获取当前优先级 mt1.setPriority(10); System.out.println(mt1.getPriority()); // 获取当前优先级// MyThread_3 mt3 = new MyThread_3();// mt3.setName(\"run\");// mt3.setDaemon(true); mt1.start(); mt2.start(); }}class MyThread_2 extends Thread{ @Override public void run() { Thread thread = Thread.currentThread(); for (int i = 0; i < 10; i++) { System.out.println(thread.getName()+\"i\"); } }}class MyThread_3 extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println(getName()+\"\"+i); } }}
4、线程的优先级
操作线程的方法
Java线程同步是一个非常重要的概念,主要用于解决多线程并发控制问题。当多个线程同时操作一个可共享的资源变量时,可能会产生数据不准确和相互冲突的问题。为了解决这些问题,Java提供了多种同步机制,包括synchronized关键字、Lock接口和AtomicInteger类等。
其中,synchronized关键字是最基本的同步机制,可以用于方法或代码块的同步。当一个线程在执行一个synchronized方法时,其他试图访问该对象的线程将被阻塞,直到第一个线程执行完毕。这样可以确保同一时间只有一个线程可以访问共享资源,避免了数据不一致和程序异常的问题。
package text_3;public class demo { public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.setName(\"窗口一\"); t2.setName(\"窗口二\"); t3.setName(\"窗口三\"); t1.start(); t2.start(); t3.start(); }}class MyThread extends Thread { static int ticket = 0; @Override public void run() { while (true) { // 同步线程:线程锁(锁对象) 需要注意的是锁对象一定是要唯一的 try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (ticket < 100) { ++ticket; System.out.println(getName() + \"正在卖第\" + ticket + \"张票\"); } else { break; } } }}
一般情况:窗口售票
通过运行结果,我们可以看出没有加线程同步的情况,多个线程对同一资源的访问,因为系统cpu轮转的情况,某一线程可能已经售出了某张票,但是另一个线程也在售出这张票,所以导致了重复售出的情况。
线程同步机制是Java多线程编程中的重要概念,主要用于解决多线程并发控制问题。线程同步机制可以让多个线程按照一定的顺序执行,避免出现数据不一致和相互冲突的问题。Java中实现线程同步的方式有多种,包括synchronized关键字、Lock接口、信号量Semaphore、倒计时门闩CountDownLatch、循环栅栏CyclicBarrier和闭包等。
其中,synchronized关键字是最基本的线程同步机制之一,可以用于方法或代码块的同步。当一个线程在执行一个synchronized方法时,其他试图访问该对象的线程将被阻塞,直到第一个线程执行完毕。这样可以确保同一时间只有一个线程可以访问共享资源,避免了数据不一致和程序异常的问题。
需要注意的是,使用synchronized块进行同步线程时,同步代码块的对象一定需要是唯一的。
运行结果: 杜绝了重复票的情况
package text_3;public class demo { public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.setName(\"窗口一\"); t2.setName(\"窗口二\"); t3.setName(\"窗口三\"); t1.start(); t2.start(); t3.start(); }}class MyThread extends Thread { static int ticket = 0; @Override public void run() { while (true) { // 同步线程:线程锁(锁对象) 需要注意的是锁对象一定是要唯一的 synchronized (MyThread.class) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (ticket < 100) { ++ticket; System.out.println(getName() + \"正在卖第\" + ticket + \"张票\"); } else { break; } } } }}
同步代码块改进
线程同步机制
线程同步
多线程
网络程序设计编写的是与其他计算机进行通信的程序。Java 已经将网络程序所需要的元素封装成不同的类,用户只要创建这些类的对象,使用相应的方法,即使不具备有关的网络支持,也可以编写出高质量的网络通信程序。
网络程序设计基础
为了实现两台计算机的通信,必须用一个网络线路连接两台算计。
服务器是指提供信息的计算机程序客户机是指请求信息的计算机或程序网络用于连接服务器与客户机,实现两者的相互通信。但是,有时在某个网络中很难将服务器与客户机区分开。局域网 (LAN) 是一群通过一定形式连接起来的计算机,它可以由两台计算机组成,也可以由同一区域内地上千台计算机组成。将 LAN 延伸到更大的范围,这样的网络成为广域网(WAN)。互联网是由无数的 LAN 和 WAN 组成的。
局域网与互联网
网络协议规定了计算机之间连接的物理、机械(网络与网卡的连接规定)、电气(有效的电平范围)等特征,计算机之间的相互寻址规则,数据发送冲突的解决方式,长数据如何分段传送与接收等内容。
IP 是 Internet Protocol 的简称,是一种网络协议。Internet 网络采用的协议是 TCP/IP协议。TCP/IP 模式是一种层次结构,共分为 4 层,分别为应用层、传输层、互联网层和网络层。各层实现特定的功能,提供特定服务和访问接口,并具有相对的独立性。
IP协议
传输控制协议(TCP)用户数据报协议(UDP)
在TCP/IP 协议栈中有两个高级协议 :
TCP/IP 协议
一般而言,一台计算机只有单一的连接到网络的物理连接,所以的数据读通过此连接对内、对外送达特定的计算机,这就是端口。网络程序设计的端口(port)并非真实的物理存在,而是一个假想的连接装置。网络程序中的套接字(Socket)用于将应用程序 与端口连接起来。
套接字是一个假想的连接装置,就像插座一样可以连接电器与电线。
端口域套接字
网络协议
TCP 网络程序设计是利用 Socket 类编写通信程序。利用 TCP 协议进行通信的两个应用程序是有主次之分的,一个称为服务器程序,另一个称为客户机程序,两者的功能和编写方法大不一样。
java.net 包中的 InterAddress 类是与 IP 地址相关的类,利用该类可以获取 IP 地址、主机地址等信息。
import java.net.*; public class Demo21_1 { public static void main(String[] args) { InetAddress ip;//创建InetAddress对象 try {//捕捉异常 ip=InetAddress.getLocalHost();//实例化对象 String ming=ip.getHostName();//获取本机名 String dizi=ip.getHostAddress();//获取本机地址 System.out.println(\"本机名:\"+ming);//输出本机名 System.out.println(\"本机IP地址:\"+dizi);//将本机IP地址输出 } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace();//输出异常 } } }
InterAddress 类
java.net 包中的 ServerSocket 类用于表示服务器套接字,其主要功能是等待来自网络上的“请求”,它可以通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字。如果多台客户机同时提供出连接请求,服务器套接字会将请求连接的客户机存入列队中,然后从中取出一个套接字,与服务器新建的套接字连接起来。若请求连接大于最大容纳数,则多出的连接请求被拒绝。队列的默认大小是 50。
ServerSocket 类的构造方法通常会抛出 IOException 异常,具体有以下几种形式:
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket; public class Demo21_2 { private ServerSocket s;//服务器套接字 private Socket sk;//客户端套接字 void start() {//启动服务器 try { s=new ServerSocket(8998);//服务器启用8998端口 System.out.println(\"服务器套接字已经创建成功\"); while(true) { System.out.println(\"等待客户机的接入\"); sk=s.accept();//监听客户机的连接 BufferedReader r=new BufferedReader(new InputStreamReader(sk.getInputStream())); while(true) {//循环接收信息 String m=r.readLine();//读取一行文本 if(\"退出\".equals(m)) {//如果客户机发来的内容为退出 System.out.println(\"客户机退出\"); break;//停止接收信息 } System.out.println(\"客户机\"+m); } r.close();//关闭流 sk.close();//关闭套接字 } }catch(IOException e) { e.printStackTrace(); } } public static void main(String[] args) { Demo21_2 tcp=new Demo21_2(); tcp.start();//启动服务器 } }
示例:创建 TCP/IP 协议服务器,本实例是一个 TCP服务器端程序。
import java.awt.BorderLayout;import java.awt.Container;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.IOException;import java.io.PrintWriter;import java.net.Socket; import javax.swing.JFrame;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField; public class Demo21_2_2 extends JFrame{ private PrintWriter w;//字符输出流 Socket s;//客户端套接字 private JTextArea area=new JTextArea();//文本域 private JTextField text=new JTextField();//文本框 public Demo21_2_2() { setTitle(\"向服务器送数据\
服务器端
ServerSocket 类
TCP 程序
用户数据报协议 (UDP) 是网络信息传输的另一种形式。基于 UDP 的通信和基于 TCP 的通信基于 UDP的信息传递更快,但不提供可靠性保证。使用 UDP 传递数据时,用户无法知道数据能否正确地到达主机,也不能确定到达目的地的顺序是否和发送相同。虽然 UDP 是一种不可靠的员议,但如果需要较快地传输信息,并能容忍小的错误,可以考虑使用 UDP。
1、将数据打包 (称为数据包),然后将数据包发往目的地。2、接收别人发来的数据包,然后查看数据包。
基于 UDP 通信的基本模式如下:
发送数据包的步骤如下:
接收数据包的步骤如下:
java.net 包的 DatagramPacket 类用来表示数据包。DatagramPacket 类的构造方法如下:
第一种构造方法在创建 DatagramPacket 对象时,指定了数据包的内存空间和大小。第二种构造方法不仅指定了数据包的内存空间和大小,还指定了数据包的目标地址和口、在发送数据时,必须指定接收方的 Socket 地址和端口号,因此使用第二种构造方法可创建发送数据的 DamgramPacket 对象。
DatagramPacket 类
javanet 包中的 DatagramSocket 类用于表示发送和接收数据包的套接字。该类的构造方法如下:
第一种构造方法创建 DatagramSocket 对象,构造数据报套接字,并将其绑定到本地主机任何可用的端口上。第二种构造方法创建 DatagramSocket 对象,创建数据报套字,并将其绑定到本地主机的指定端口上。第三种构造方法创建 DatagramSocket 对象,创建数据报套接字,并将其绑定到指定的端口和指定的本地地址上。第三种构造函数适用于有多块网卡和多个 IP 地址的情况。
import java.io.IOException;import java.net.DatagramPacket;import java.net.InetAddress;import java.net.MulticastSocket; public class Demo21_3 extends Thread{ String weather=\"节目预报:八点有大型晚会,请收听\"; int port=9898; InetAddress iaddress=null; MulticastSocket socket=null; Demo21_3(){ try { iaddress=InetAddress.getByName(\"224.225.10.1\
发送数据部分:
接收数据部分:
示例:创建 UDP 协议广播电台程序,广播主机程序不断地向外播出信息。
DatagramSocket 类
UDP 程序
网络通信
Java从入门到精通(12~21章)
收藏
0 条评论
回复 删除
下一页