Java基础—网络编程(二)

@[toc]网络编程(二) 一、TCP协议通信 1.上传图片练习1)将图片上传到服务器端保存。 示例代码: 程序运行结果:上传成功 2)TCP客户端并发上传图片这个服务端有局限性。当一个客户端连接服务器之后,因为服务器是单线程,那么其他客户端如果想连接服务器,只能带前一个客户完成所有任务,才能连接。要同时处理多个客户端请求,应该明确客户端要在服务器端要执行的代码,然后将每个客户端封装到一个线程当中,同步执行。 示例代码: 2.检测用户名练习客户端通过键盘录入用户名,如果该用户存在,在服务器端显示xxx,已登录;在客户端显示xxx,欢迎光临。如果用户不存在,在服务端显示xxx,尝试登录;在客户端显示xxx,该用户不存在。 示例代码: 3.自定义浏览器1)HTTP请求消息头请求头信息中包括了发送该请求的主机地址,端口,路径,可以接受的应用程序类型,所使用语言,封装压缩形式等信息。请求头信息示例如下: 模拟一个浏览器,想服务器发送请求头信息,获取页面。 示例代码: 二、URL类 1.概述URL(Uniform Resource Locator)类代表一个同一资源定位符。该类是指向互联网资源的指针。 2.常用方法-String getFile():获取此URL的文件名-String getHost():获取此URL的主机名-String getPath():获取此URL的路径部分-int getPort():获取此URL的端口号-String getProtocol():获取此URL的协议名称-String getQuery():获取此URL的查询部 3.常用方法演示 示例代码: 程序运行结果: 注意:没有指定端口,返回-1;开发时要进行判断,如果port的值为-1,要给port赋值为80 三、URLConnection类 1.概述URLConnection类对象是URL对象调用openConnect()方法之后的返回值,就能得到这个URL的连接对象,也就是目标主机对象;获取URLConnection对象可以方便获取Socket输入流对象。 2.URLConnection类演示 示例代码: 注意:url.openConnection().getInputStream()这行代码,可以简写成url.openStream();该方法是URLConnection类中获取InputStream的便捷方法 四、扩展知识 1.Socket空参数构造函数通过调用connect()方法连接主机;connect()方法可以接收一个SocketAddress对象作为参数;SocketAddress类的子类InetSocketAddress类封装IP地址和端口;那么以前在创建Socket对象的时候分开写主机IP和端口,现在也可以调用connect方法,传递一个InetSocketAddress对象即可。 2.ServerSocket类接收的backlog参数backlog表示队列的最大长度。它代表能同时连接到服务器的最大客户端个数。在服务器端开发时,要指定这个参数,避免服务器因连接数过多而死机。 五、域名解析 1.概述IP地址不容易记忆,通常人们在访问网站的时候,在地址栏输入的都是类似于www.baidu.com这样的域名。但是要访问到网络上对应这个域名的那个主机,需要将这个域名解析成IP地址。这个过程,需要DNS域名解析服务器来完成。DNS服务器中记录的是每个域名对应的IP地址映射表。 2.基本原理 PC在访问网站的时候,要走这4步流程。在浏览器输入域名之后,第1步,到本机C盘“(C:\windows\Systems\drivers\etc\)下的hosts文件,寻找这个域名是否在本地有已经配置的IP地址,如果有,直接访问该IP,否则,进入第2步;第2步,访问公网DNS服务器,找到DNS服务器上的域名——IP映射关系;第3步,DNS服务器将对应的IP地址返回给PC;第4步,PC端访问该IP地址,找到公网上的指定主机。 注意:127.0.0.1与localhost之间的映射关系在本机上C盘下的hosts文件中。该文件可以用于屏蔽恶意网站。

Java基础—网络编程(一)

网络编程(一) 一、网络模型 1.OSI参考模型OSI网络模型的每一层,都有自己特有的数据封装特征信息。两台主机通信,首先在应用层将数据封装。将会给数据加上应用层的特征信息,传递给OSI网络模型的下一层表示层;表示层也会给数据加上自己特有的特征;以此类推。到传输层(TCP/IP和UDP协议所在层),加上TCP的特征信息,交由网络层;网络层将IP协议赋给该数据包,标识该数据包的目的地,再交给数据链路层;数据链路层标识该数据包的传输方式,交给最后一层物理层(网线,光纤,无线设备);这时,数据封包结束,通过物理层传输到目的主机的物理层,由对方主机,从底层物理层开始,对数据进行数据拆包。 2.TCP/IP参考模型TCP/IP参考模型分为四个层次。它将OSI参考模型的应用层、表示层和会话层合并为应用层,保留了传输层和网际层,最后将数据链路层和物理层合并为主机至网络层。 注意:把用户应用程序最为最高层,把物理通信线路最为最底层,将其间的协议处理分为若干层,规定每层处理的任务,也规定每层的接口标准。网络模型的每个层次都有自己的传输协议。传输层的协议是TCP和UDP协议;网际层最常用的是IP协议;应用层通常使用HTTP/FTP协议 二、网络通信三要素 1.对方IP地址网络通信的首要素是要知道对方的IP地址,确定对方的主机在网络上的位置,才能发起进一步的请求。 2.应用端口网络通信第二要素是获取对方的端口。要将数据要发送到指定的应用程序上,就必须直到对方用于接收本方数据的应用服务端口。每个网络应用程序都有一个网络端口用于接收数据。主机上的端口可以在0-65535之间任取,但是0-1024默认作为系统端口,不建议使用。 3.通信协议通信协议,即通信规则。国际组织定义了一个在传输层和网络层通用的协议————TCP/IP协议。 三、IP地址 1.概述IP(Internet Protocol)协议是网际层的主要协议,支持网间互连的数据包通信。它提供无连接数据包传送,数据包路由选择和差错控制。IP地址分4段,每段为1个字节,每段最大值为255。IP地址用于确定主机在网络中的位置。 2、本地回环地址127.0.0.1是本地回环地址,可以用于测试网卡工作是否正常或这用于测试本地网页等。 3.局域网IP地址192.168开头的IP被保留,不用于公网,用于局域网。其中有一个例外,第四个字段为255的被保留作广播IP地址,给这个IP发送的消息,局域网内所有主机都能接收。 4.子网掩码子网掩码用于划分局域网。由于主机数量越来越多,出现了IP不够的情况。划分子网,让多台主机使用同一个公网IP,部分解决了这一问题。 5.域名IP地址有4段,不易记忆,通常给主机起一个名字,如127.0.0.1称为localhost,这就是127.0.0.1这个IP地址的域名。 四、通信协议 1.UDP协议1)概述UDP(user data protocol)向应用程序提供了一种发送封装的原始IP数据包的方法。该协议面向无连接,通信主机一端只负责发送数据,不负责对方是否接收到数据;如果对方处于在线状态,就能接收到数据包;如果不在线,该数据包就丢失。UDP在传输数据时,两通信主机不一定已经建立连接。 2)特点1> 将数据、数据源和目的封装成数据包;2> 数据包大小有限制,限制在64k以内;3> 不需要建立连接,协议不可靠4> 速度快,效率高 2.TCP协议1)概述TCP(transmission control protocol)是专门设计用于在不可靠的因特网上提供可靠的、端到端的字节流通讯协议。它是一种面向连接的协议。TCP与UDP协议相反,是面向连接的协议。该协议在传输数据前必须先建立连接。这个连接的建立是基于三次握手的机制之上的。三次握手确保了数据连接通路的存在,一旦通信双方有一方断开连接,数据传输即刻停止。 2)特点1> 数据传输大小无限制2> 通过三次握手机制确定连接通路畅通3> 必须建立连接,协议可靠4> 速度较慢,效率较低 五、网络编程常用类 1.Socket类1)概述网络编程其实就是Socket编程。Socket是为网络服务提供的一种机制,是通信得以进行的前提。通信两端的主机都有Socket,两端通信其实就是Socket间在通信,数据在两个Socket间通过IO进行传输。TCP和UDP协议,都是基于Socket进行数据传输。 2)不同协议的Socket创建每个传输协议都有自己建立传输端点的方式。下面进行不同协议的Socket服务的建立。 UDP协议建立发送端SocketDatagramSocket和DatagramPacket类DatagramSocket类表示用来发送和接收数据包的套接字(Socket)。该类既能发送,又能接收。DatagramSocket在发送数据时,提供了数据包对象DatagramPacket,用于数据封包。 第一步:建立发送端UDPSocket服务 第二步:提供数据,并将数据封装到数据包中 第三步:通过Socket服务发送数据包 第四步:关闭资源 UDP协议建立接收端Socket 第一步:建立接收端UDPSocket服务 第二步:定义数据包对象 第三步:通过Socket服务接收数据包 第四步:解析数据包 第五步:关闭资源 程序运行结果:127.0.0.1::UDP ge men er lai la !~~#!@$@%#^$&::64979 注意:UDP接收端的receive()方法是阻塞式方法…

Java基础—IO流(三)

IO流(三) File类 一、概述 File类用于将文件或文件夹封装成对象,方便对文件和文件夹的属性信息进行操作。该类可以作为参数传递给IO流的构造函数,弥补流对象在操作文件和文件夹上的缺陷。 二、File类的使用 1.构造方法1)File(String FileName)示例:File f1 = new File(“C:\\abc\\a.txt”); 2)File(Strng, parent, String FileName)示例:File f2 = new File(“C:\\abc”, “b.txt”);该构造方法的好处在于对文件的操作更加灵活,出现文件目录固定,文件名需要改变的时候,这个构造方法更好 3)File(File parent, String FileName)示例:File d = new File(“C:\\abc”); File f3 = new File(d, “c.txt”); 示例代码: 程序输出结果: 打印封装文件对象时的绝对路径或相对路径。 2.成员方法1)创建操作-boolean createNewFile():文件名不存在的情况下创建新文件-boolean mkdir():创建一级目录-boolean mkdirs():创建多级目录 2)删除操作-boolean delete():删除指定文件-void deleteOnExit():虚拟机退出的时候删除指定文件 3)判断操作-boolean canExecute():判断文件对象是否可执行-boolean canRead():判断文件对象是否可读-boolean canWrite():判断文件对象是否可写-boolean exists():判断文件对象是否存在-boolean isDirectory():判断文件对象是否是文件夹,判断之前,必须先判断该文件对象是否存在-boolean isFile():判断文件对象是否是文件,判断之前,必须先判断该文件对象是否存在-boolean isHidden():判断文件对象是否是隐藏文件-boolean isAbsolute():判断文件对象路径是否是绝对路径-int compareTo(File pathname):比较两个文件对象,以自然顺序排序 4)获取操作-String…

Java基础—IO流(二)

IO流(二) 字节流 一、OutputStream类 1.概述OutputStream类可以在硬盘上创建一个文件,并写入或添加数据。该类的子类还能实现写入过程中的不同功能。 2.FileOutputStream类FileOutputStream类用于在硬盘上创建文件,并以字节的形式写入数据。其使用方式和FileWriter类相似,只是以字节的形式操作数据。下面的代码在指定目录创建一个文件并写入自定义数据。 示例代码: 该程序在指定目录创建fos.txt并写入abcdefg 注意:字节输出流在直接使用的时候不需要调用flush()方法,与字符流不用。由于字符流底层操作的也是字节,同时用的是字节流的缓冲区;该缓冲区中有个数组,用于临时存储数据。要将数组中的数据写入目的地文件,字符流就需要调用flush()方法进行刷新。而字节输出流是对最小单位字节直接进行操作,没有使用具体缓冲区,所以不需要刷新,直接往目的地文件写入数据。 二、InputStream类 1.概述InputStream类以字节形式读取硬盘上的文件数据。该类的子类还能实现读取过程中的不同功能。 2.FileInputStream类FileInputStream类用于以字节形式读取文件数据。其特有的方法使创建字节数组有了明确的大小。该类的使用方式和FileReader相似。下面的代码读取文件中的数据。 示例代码: 程序输出结果: 注意:如果使用字节输入流读取的文件较大,建议使用1024字节整数倍方法读入数据,而不要使用创建available()方法返回值大小的数组;后者可能造成内存溢出 三、字节流练习 1.拷贝图片到指定目录 示例代码: 四、字节流缓冲区 1.缓冲区对应的类字节流缓冲区对应BufferedOuputStream类和BufferedInputStream类。 2.缓冲区应用1)用缓冲区拷贝一个Mp3文件 示例代码: 程序输出结果:136毫秒 2)自定义缓冲区 假设内存中字节数组的大小定义为1024字节;那么字节流缓冲区在工作时,首先由FileInputStream从硬盘抓取1024字节的数据存入字节数组,然后由BufferedInputStream的read()方法依次一个字节一个字节读取。缓冲区中有两个控制读取过程的变量,分别是数组的索引指针,和一个计数器。下标用于控制不断读取下一个字节,计数器用于控制下一次从硬盘抓数据存入缓冲区数组的时间。read()方法每读取一个字节,指针右移一位,计数器自减1;当计数器减至0的时候,意味着数组中已经没有字节可读,这时再由FileInputStream从硬盘抓取1024个字节存入数组,指针归零,计数器回到1024,再次进行以上步骤的循环,直至硬盘数据全部被抓取。 要自定义缓冲区,需要定义一个字节数组,两个变量(指针和计数器)。 示例代码: 问题:上面的代码运行结果只拷贝了8K到目的文件。 原因:是因为媒体文件在硬盘上的数据以二进制形式存在;read()方法在读取第一个字节的时候,有可能会读到:11111111;这样8个1的情况;而8个1的的二进制就是十进制的-1;程序中while循环的跳进等于-1时,循环停止;因此只复制了8K大小。 理解BufferedInputStream的read()方法:细看BufferedInputStream类的read()方法,其返回的是int类型。而方法中读到的字节都是byte类型;这样做的原因,就是为了解决读取字节读到8个1的情况。read()方法在返回byte类型字节数据的时候,将byte类型提升为int类型,存储位数由1个8位,变为4个8位。为了确保返回的数据与原数据相同而不产生-1的情况,read()方法在类型提升之后,补了3个8位的0在原byte数据前面。过程如下图: 在自定义缓冲区中,虽然方法返回了int类型,进行了数据类型提升,但是没有进行补0的操作,意味着当读到8个1组成的byte数据时,返回了一个由32个1组成的int类型数据,结果还是-1。那么,如果要完成相同功能,只需取32个1的最后8位即可。取最后8位,将原数据与上255。 将每个return ch;语句改为return ch & 255;即可。 五、键盘录入 1.System标准输出输入System类中对应的成员out和in分别是:System.out-标准输出流System.in-标准输入流 System.in用于读取键盘录入。 2.接收键盘录入从键盘接收输入,并打印在控制台。 示例代码: 程序输出结果: 3.练习接收键盘录入,当回车时打印整行内容;当输入over回车时,结束输入。 示例代码: 六、转换流 1.InputStreamReader类InputStreamReader类用于将字节流转换为字符流。该类可以将读取到的字节数据转换为字符数据。其使用的编码表可以由开发者指定,也可以使用系统默认。利用转换流将字节流转换为字符流,就意味着该字节流可以使用字符流的缓冲区技术,调用其readLine()方法,使键盘录入的读取过程更加高效便捷。 利用转换流修改键盘录入并打印的代码: 将字节流转换为字符流,相当于在字节流上套了两根管子;一根使字节流变成字符流;另一根使字节流可以使用字符流的缓冲技术。 2.OutputStreamWriter类OutputStreamWriter类用于将字符流转换为字节流。该类的编码表同样可以指定或使用系统默认。 用OutputStreamWriter类修改上面的代码: 可以将字节流转字符流的三个步骤简化为一行代码: 3.转换流的作用转换流可以指定读写时使用的字符编码集;如不指定,将使用系统默认的编码集,本机默认使用GBK。下面的代码演示了用UTF-8写入,用GBK读取会发生乱码的情况。 示例代码: 程序输出结果: 为了正常显示,用InputStreamReader指定读取时编码集为UTF-8即可 程序输出结果:…

Java基础—IO流(一)

IO流概述 一、概述 Java对数据的处理都是通过流的方式,称为IO(Input-Outpu)流。IO流用于处理设备上的数据传输,如硬盘上储存的数据,内存中驻留的数据。 二、IO流的区分 1.按流向分按流向分为:输入流和输出流。 2.按操作数据分流按操作数据分为两种:字节流与字符流。 小扩展:字符流的出现是为了方便处理文本字符。英语有英文字符集ASCII码;中文字符集由原来的GB2312,扩展为现在的GBK。之后,国际标准化组织计划将世界上所有国家的文字都进行编排,形成了国际标准码表,UNICODE;优化之后,形成了UTF-8字符编码表。那么,如果一个电脑用GBK编码存储文本,另一个电脑用UTF-8编码读取,就会出现乱码。Java就这个情况,在字节流的基础上,增加了字符流。字符流内部融合了编码表,并可以指定查询的编码表,处理文本字符更加方便,避免乱码。 三、IO流常用基类 1.字符流的抽象基类 Reader Writer 2.字节流的抽象基类 InputStream OutputStream IO流用于操作数据,数据的最常见体现形式是文件。那么以操作文件为主,从字符流开始,来演示IO流程序。 IO流(一) 字符流 一、Writer类 1.概述Writer类可以在硬盘上创建一个文件,并写入或添加数据。该类的子类还能实现写入过程中的不同功能。 2.FileWriter类FileWriter类专门用于操作文件。该对象中只有构造方法,并且没有空参数的构造方法,因为初始化的时候必须要有文件对象,才能进行写入操作。在示例代码中,将对每个环节做详细注释。 1)文件创建并写入 第一步:创建FileWriter对象,传入要操作的文件名 注意:-创建文件会报出异常,此处先抛出,后期会有专门处理异常的代码;-如果指定文件夹下有同名文件,该文件将被覆盖,所以要小心创建操作 第二步:写入自定义数据 注意:-writer()方法不是将文本内容直接写入文件,而是先写入流的缓冲区;-flush()方法将缓冲区中的内容写入到文件;每次调用完writer()方法,都要调用flush() 第三步:关闭流资源 注意:-由于每个系统创建文件写入内容的方式不同,Java需要调用系统底层的功能来实现文件的创建和写入;使用完系统资源的之后,一定要调用close()方法,关闭该资源;-close()方法与flush()方法的区别在于,close()方法刷新缓冲区之后,关闭了该输出流资源,之后不能再写入数据;而flush()之后,可以继续写入数据,流资源依然存在; 第四步:针对处理IO异常 注意:-用try catch捕捉并处理异常;-关闭资源的代码一定要放在finally中;-close()方法同样会抛出IO异常,同样需要用try catch捕捉并处理;-如果创建文件的路径有误(例如电脑上没有k盘,创建时却写fw = new FileWriter(“k:\”demo.txt”);),那么会报出FileNotFoundException文件无法找到异常,同时会报出NullPointerException空指针异常,因为路径找不到,fw对象没有建立,而finally中还要调用close()方法,会发生空指针异常;所以需要在finally中建立判断;-无论读、写数据还是关闭资源操作,都有可能发生IO异常 2)文件的续写在原有数据的基础上,续写自定义数据。 第一步:修改构造方法 第二步:写入自定义数据 二、Reader类 1.概述Reader类用于高效读取字符流。该类的子类可以实现读取过程中的不同功能。 2.FileReader类FileReader类是用于读取字符文件的便捷类。该类包含默认的字符编码和默认的字节缓冲区大小。 1)read()方法读取文件 第一步:创建FileReader对象 注意:创建FileReader对象时关联的读取文件必须已经存在,不然会发生FileNotFoundException 第二步:读入单个字符并关闭资源 注意:read()方法读到文件末尾没有字符的时候,会返回-1;可以利用这个机制,循环读取所有数据 第三步:一次性读取全部数据 2)read(ch[] ch)方法读取文件 第一步:定义一个字符数组用于储存读到的字符 第二步:读取字符并存入字符数组 注意:read(ch[] ch)方法返回的是读取了多少个字符;独到文件末尾,返回-1;可以利用这一机制,循环读取全部字符 第三步:一次性读取全部数据 注意:-缓冲区字符数组通常定义1024的整数倍长度;-read(ch[] ch)方法的效率优于read()方法;由于read()方法读一个字符,写一个字符,效率低下;而raead(ch[]…

Java基础—集合框架(四)

集合框架(四) 一、集合框架工具类 1.Collections工具类1)定义Collections工具类用于对集合进行各种操作。 2)常用方法1> 排序操作 格式:static void sort(List list):自然排序static void sort(List list, Comparator c):自定义排序 示例代码: 程序输出结果: [z, qq, zz, aaa, abcd, kkkkk] 2> 获取最大元素 格式:static max(Collection coll): 根据元素的自然顺序,返回指定collection中的最大元素static T max(Collection coll, Comparator comp):获取指定排序下的最大元素 示例代码(以上述代码为例): Collections.max(list);程序输出结果:zz Collections.max(list, new StrLenComp());程序输出结果:kkkkk 3> 二分搜索 格式:static int binarySearch(List<? extends Comparable<? super T>> list, T key):搜索指定元素static int binarySearch(List<? extends T> list,…

Java基础—集合框架(三)

集合框架(三) 一、Map集合 1.概述Map集合用于存储键值对,且它保证键的唯一性,并且每个键最多只能映射一个值。Map集合是Set集合的底层实现,其和Collection在集合框架中并列存在。 2.Map集合共性方法1)添加操作 -V put(K key, V value):添加指定的键值对-void putAll(Map<? extends K, ? extends V>, m):添加指定Map集合 注意:put()会返回该键对应的被覆盖的值第一次存储put(“01”, “zhangsan”);返回null;”01″键对应的被覆盖的值为null;第二次存储put(“01”, “wangwu”);返回”zhangsan”;”01″键对应的被覆盖的值为”zhangsan”; 2)删除操作 -void clear():清楚所有映射关系-V remove(Object key):根据键删除映射值 3)判断操作 -boolean containsKey(Object key):判断是否包含指定键的映射关系-boolean containsValue(Object value):判断是否包含指定值的映射关系-boolean isEmpty():判断是否为空 4)获取操作 -V get(Object Key):通过键获得值-int size():获取Map长度-Collection values():返回所有的映射的值-Set entrySet():返回包含的映射关系-Set keySet():返回包含的键 3.Map集合子类 Map HashTable HashMap TreeMap 1)HashTableHashTable底层是哈希表数据结构。此类实现一个哈希表,该哈希表将键映射到相应的值上。任何非null的对象都可以做键或值。为了成功在哈希表中存储和获取对象,用作键的对象必须实现hashCode()方法和equals()方法。HashTable类是线程同步的。 2)HashMapHashMap底层是哈希表数据结构。此类与HashTable大致相同,但允许使用null的对象作为键或值。HashMap不保证映射的顺序,特别是它不保证该顺序恒久不变。HashMap类是线程不同步的,效率高于HashTable。 3)TreeMapTreeMap底层是二叉树数据结构。此类可以实现为Map集合中的键排序。TreeMap线程不同步。 4.Map集合方法应用演示Map集合基本方法。 示例代码: 程序输出结果: 5.Map集合元素取出方式1)keySet()方法将Map中所有的key存入Set集合,再通过Set集合的迭代器将所有key取出,最后通过get()方法获取每个key的对应值。 示例代码: 程序输出结果: 2)entrySet()方法将Map集合中的映射关系存入到Set集合中。该关系的数据类型是Map.Entry。 示例代码:…

Java基础—集合框架(二)

集合框架(二) 一、TreeSet 1.TreeSet集合特点可以对Set集合中的元素进行自然排序。往TreeSet里面的对象,必须具有比较性,才可以实现排序。 2.TreeSet集合排序实现方式1)元素实现Comparable接口要获得元素的比较性,需要进行存储的对象可以实现Comparable接口,并复写compareTo()方法,自定义比较方式;这是通过让元素获得比较性的方法,完成TreeSet排序功能。 2)集合初始化Comparator当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时可以让集合调用具备比较功能的构造方法,将比较器对象作为参数传给TreeSet集合的构造方法;这是让集合自身具备比较功能,完成TreeSet排序。 注意:-TreeSet集合保证元素唯一新的依据是comparteTo()方法的返回值为0;-当元素和集合都具备比较功能时,以集合的比较器为主 3.TreeSet集合运用1)继承Comparable接口的方法实现元素的可比性使用TreeSet集合存储自定义对象。 示例代码: 程序输出结果: 注意:排序时,当主要条件相同时,一定要判断次要条件 2)调用TreeSet具备比较器构造方法 示例代码: 程序输出结果: 4.二叉树数据结构1)定义 二叉树数据结构的原则是将小的元素依次放在左边,大的元素依次放在右边。在取数据时,二叉树从最小的元素开始,依次往上取到最大值。这样的数据结构,可以减少比较次数,提高运行效率。 2)二叉树运用使用二叉树原理实现数据存储和取出顺序一致。 示例代码: 要使存储和取出的顺序一致,只需在复写的compareTo()方法中,return 1;即可;存储与取出成倒序,只需return -1;即可 5.TreeSet练习1)按照字符串的长度排序 示例代码: 程序输出结果: 二、泛型 1.概述 由一个小例子引出泛型: 如果没有泛型的支持,后添加的整型数据4,在运行时会出现运行时期类型转换异常,int类型无法被转换为String类型,但是这个异常在编译时期,没有任何提示。为了避免这样的情况,需要程序在编译时期就给出异常,以便开发者解决问题,Java引入了泛型机制。 JDK5.0版本之后的新特性,用于解决集合存储的安全问题。 泛型格式(以储存String类型数据为例): ArrayList<String> arrayList = new ArrayList(); 声明一个ArrayList容器,存储String类型的元素。这样,上述程序在编译时期就会报出异常。容器声明加上了泛型,那么迭代器的声明也应加上泛型: Iterator<String> it = arrayList.iterator(); 2.泛型的优点1)将运行时期出现的ClassCastException转移到编译时期,方便开发者解决问题,更安全;2)避免了迭代时期类型强制转换的麻烦;3)泛型类的出现优化了程序设计 3.泛型的应用当在声明容器的时候指定了泛型,后期实现Comparator接口和Comparable接口的时候,可以指定Comparator接口的泛型;这样做,避免了比较时的类型转换。 Comparator接口泛型示例代码: Comparable接口泛型示例代码: 注意:复写equals()方法的时候,传的参数必须是Object obj;因为Object类没有泛型 4.泛型类1)定义泛型类是在一个类要操作对象,而对象类型又不明确时出现的。 2)泛型类格式声明泛型类,只需要在类名后加上<T>即可:class GenericClass<T> 3)泛型类应用当一个类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型来完成扩展。例如,当一个工具类中要操作不同的对象Worker和Student时,早期通过接收Object对象,然后通过类型转换类完成操作;现在只需定义泛型,无需类型转换。 早期实现: 如果现在要操作的是Worker对象,而在setObject()方法中误传入了Student对象,编译不会报错,但是运行时会出现类型转换异常。 泛型实现: 如果现在要操作的是Worker对象,而在setObject()方法中误传入了Student对象,编译无法通过;并且泛型实现无须进行类型转换,既简化了代码,又提升了安全性。5.泛型方法1)定义泛型类在使用的过程中有其局限性。例如一个泛型类被定义了只能操作String类型的对象,那么该类中需要接收参数的方法,都只能操作String对象;此时如果给该类中的方法传递了非String类型数据,编译就会出错。为了程序更加灵活,现在想实现一个类中不同的方法操作不同类型的对象,而要操作的对象不能确定,那么就可以使用泛型方法。 2)泛型方法格式要声明泛型方法,只需在方法修饰符后面,返回值的前面加上<T>即可:private <T>…

Java基础—集合框架(一)

集合框架(一) 一、概述 1.集合出现的原因Java中,数据被封装成对象;对象完成了对数据的存储。而集合的出现,完成了对对象的存储,方便对对象进行操作。 2.集合与数组的区别1)数组虽然可以存储对象,但是长度固定,不利于后期扩展;只能存储同一类型对象;2)集合的长度是可变的;并且能存储不同类型对象 3.集合的特点1)长度可变;2)可以存储不同类型的对象;3)集合只用于存储对象,不能存储基本数据类型 二、Collection 1.定义Collection是集合框架层次结构中的根接口。Collection提供了具体的自接口(如Set和List)实现。这个根接口用来传递collection,并提供共性方法,操作这些collection。 2.共性方法1)添加操作 -boolean add(E e):添加指定元素到集合中-boolean addAll(Collection<? extends E> c):添加指定集合中的所有元素到当前集合中 2)判断操作 -boolean contains(Object o):判断当前集合中是否包含指定元素-booean isEmpty():判断当前集合是否为空 3)删除操作 -void clear():清空当前集合-boolean remove(Object o):移除指定元素-boolean removeAll(Collection<?> c):指定一个集合,将该集合中的元素从当前集合中移除 4)获取操作 -int size():获取当前集合长度-booean retianAll(Collection<?> c):取当前集合与指定集合的交集-Iterator iterator():迭代器,用于取出集合中元素 3.共性方法演示演示Collection中的共性方法。 示例代码: 注意:-add()方法的参数类型是Object,以便于接受任意类型对象;-集合中存放的不是对象实体,存储的是对象内存地址 三、迭代器 1.定义迭代器是对Iterator接口的实现,用于取出集合中的对象,以便于对对象进行操作。 容器的取出操作,不足以用一个方法描述。每个容器的取出操作过程,都有所不同。因此,容器将取出操作封装成一个对象,对象中提供了多个功能以实现容器对象的取出操作。 每个容器类的内部,都定义了做取出操作的内部类(便于直接访问容器内部的元素),用于取出各容器不同数据结构中的对象。这个取出操作被称为迭代器。无论是什么容器,其迭代器的操作都会有判断和取出的操作,将这些操作提取之后形成了Iterator接口。每个容器通过调用iterator()方法,获得自身的迭代器。 2.迭代器的使用iterator()方法返回的是一个Iterator接口的子类对象1)获取iterator迭代器:Iterator it = arraylist.iterator();2)调用next()方法获取第一个元素并打印:System.out.println(it.next());3)调用hasNext()方法,循环取出所有元素 四、List 1.List集合的特点List集合中的元素是有序的,并可以重复。该集合体系有索引。 2.List集合特有方法凡是操作索引的方法都是该体系特有的方法。1)添加操作 -void add(int index, E element):添加指定元素-boolean addAll(int index, Collection<?…

Java基础—String类

一、String类 1.概述1)字符串解读String s1 = “abc”; s1是一个类类型变量,”abc”是一个对象。只要在””里的,都是对象。字符串最大的特点在于,一旦初始化,就不可以改变。字符串,既是对象,又是常量。 示例:String s1 = “abc”;s1 = “kk”;System.out.println(s1); 输出结果为:kk变化的不是”abc”这个对象,而是s1这个引用;重新赋值后,s1指向了”kk”这个对象。 2)字符串创建方式的区别 高能:String s1 = new “abc”;String s2 = new String(“abc”);s1和s2的区别在于,s1有一个对象,s2有两个对象。s2中,new是一个对象,”abc”是一个对象。 小扩展字符串在内存中有常量池,该常量池是一个数组,用于存储’a’,’b’,’c’这样的字符;字符串由字符组成,如果常量池中有’a’,’b’,’c’,’d’,’e’,’f’这些字符,下次创建String s3 = “abf”;的时候,虚拟机会到常量池中找到这三个字符,拼接起来。 3)String类的equals()方法String类复写了Object类中的equals()方法,该方法用于判断字符串是否相同。 示例:String s1 = new “abc”;String s2 = new String(“abc”);System.out.println(s1.equals(s2)); 输出:true 4)String的“==”操作符比较 示例代码: 输出结果为: 字符串储存在常量池当中,当s1创建的时候,”abc”对象已经在内存中存在了;那么,当s3创建的时候,如果常量池中已经有”abc”字符串的字符,就不会再创建对象,而直接让s3指向”abc”这个对象。2.String类中的方法String类是用于描述字符串这个事物。其常见的方法有:1)获取操作1> 获取字符串长度:int length()2> 获取指定位置上的字符:char charAt(int index)3> 获取指定字符的位置有如下方法: a.int indexOf(int ch):获取指定字符第一次出现的位置b.int indexOf(int ch, int fromIndex):获取指定字符从fromIndex位置开始,第一次出现的位置c.int…