一:对象模块。
一.初始化
1.对this.super,构造函数,构造代码块,静态代码块总结。
二.继承(extends):
1.重写和重载
三.接口(implements)
1.实现
四.多态
体现:父类或者接口的引用指向自己的子类对象。(注意:在使用多态时,要访问子类的方法,要求父类中必须对该方法进行了声明或者定义)。
多态在子父类中的成员上的体现的特点:
五:内部类。
当内部类定义在外部类的成员变量位置。可以使用一些成员修饰符进行修饰默认,private,static.
1.默认修饰符。
2.private修饰符。
3.静态修饰符。
注意:如果内部类中定义了静态成员,那么该内部类必须是静态的。
当外部类的静态方法访问内部类时,内部类也必须是静态的。
当内部类被定义在局部位置上时。
匿名内部类:
意义:没有名字的内部类,是内部类的简化形式,一般内部类只用一次的话就可以用这种形式。匿名内部类其实就是一个匿名子类对象,想要定义匿名内部类:需要前提,内部类必须实现一个接口或者继承一个类。
六:异常。
异常,在子父类进行覆盖时,有以下特点:
注意:throw下面不能写语句,因为执行不到(会出现编译错误,和return,break后面不能写代码类似),但是注意如果是分支结构,也就是说if语句内写是可以的。
七:多线程。
1.相关概念。
2.线程的几种状态:
3.两种线程的创建方式
4.线程安全问题
八:同步(锁)。
1.Java中提供了一个解决方式,就是同步代码块。也就是锁。
2.另一种表现形式就是同步函数:就是将同步关键字定义在函数上,让函数具备了同步性。
3.关于同步代码块和同步函数的区别?
4.死锁。多个同步进行嵌套导致,相互等待。
九:字符串,字符容器。
1.关于字符串的方法就不过多提了,就简单的说下这里容易出错的几个概念。
十:集合框架:用于存储数据的容器。
--java.util >-- Collection接口:
Collection:
|--List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。
|--Set:无序(存入和取出顺序有可能不一致),不可以存储重复元素。必须保证元素唯一性。
--java.util >-- Iterator接口:
迭代器:是一个接口。作用:用于取集合中的元素。
boolean | hasNext() 如果仍有元素可以迭代,则返回 true。 |
next() 返回迭代的下一个元素。 | |
void | remove() 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。 |
每一个集合都有自己的数据结构,都有特定的取出自己内部元素的方式。为了便于操作所有的容器,取出元素。将容器内部的取出方式按照一个统一的规则向外提供,这个规则就是Iterator接口。
也就说,只要通过该接口就可以取出Collection集合中的元素,至于每一个具体的容器依据自己的数据结构,如何实现的具体取出细节,这个不用关心,这样就降低了取出元素和具体集合的耦合性。
-java.util >-- List接口:
List本身是Collection接口的子接口,具备了Collection的所有方法。现在学习List体系特有的共性方法,查阅方法发现List的特有方法都有索引,这是该集合最大的特点。
List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。
|--ArrayList:底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快。
|--LinkedList:底层的数据结构是链表,线程不同步,增删元素的速度非常快。
|--Vector:底层的数据结构就是数组,线程同步的,Vector无论查询和增删都巨慢。
对于List的遍历,不仅可以使用Iterator接口,也可以使用下表(索引)来遍历,list.get(index);--java.util >-- Set接口:
Set接口中的方法和Collection中方法一致的。Set接口取出方式只有一种,迭代器。
|--HashSet:底层数据结构是哈希表,线程是不同步的。无序,高效;
HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。
当元素的hashCode值相同时,才继续判断元素的equals是否为true。
如果为true,那么视为相同元素,不存。如果为false,那么存储。
如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。
|--LinkedHashSet:有序,hashset的子类。
|--TreeSet:对Set集合中的元素的进行指定顺序的排序。不同步。TreeSet底层的数据结构就是二叉树。
哈希表的原理:
1,对对象元素中的关键字(对象中的特有数据),进行哈希算法的运算,并得出一个具体的算法值,这个值 称为哈希值。
2,哈希值就是这个元素的位置。
3,如果哈希值出现冲突,再次判断这个关键字对应的对象是否相同。如果对象相同,就不存储,因为元素重复。如果对象不同,就存储,在原来对象的哈希值基础 +1顺延。
4,存储哈希值的结构,我们称为哈希表。
5,既然哈希表是根据哈希值存储的,为了提高效率,最好保证对象的关键字是唯一的。
这样可以尽量少的判断关键字对应的对象是否相同,提高了哈希表的操作效率。
6.在HashSet中尽量不要改变参与运算hashCode值的变量,以防止内存泄露。。
对于ArrayList集合,判断元素是否存在,或者删元素底层依据都是equals方法。
对于HashSet集合,判断元素是否存在,或者删除元素,底层依据的是hashCode方法和equals方法。
TreeSet:
用于对Set集合进行元素的指定顺序排序,排序需要依据元素自身具备的比较性。
如果元素不具备比较性,在运行时会发生ClassCastException异常。
所以需要元素实现Comparable接口,强制让元素具备比较性,复写compareTo方法。
依据compareTo方法的返回值,确定元素在TreeSet数据结构中的位置。
TreeSet方法保证元素唯一性的方式:就是参考比较方法的结果是否为0,如果return 0,视为两个对象重复,不存。
注意:在进行比较时,如果判断元素不唯一,比如,同姓名,同年龄,才视为同一个人。
在判断时,需要分主要条件和次要条件,当主要条件相同时,再判断次要条件,按照次要条件排序。
TreeSet集合排序有两种方式,Comparable和Comparator区别:
1:让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法。
2:让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数。
第二种方式较为灵活。
Map集合:
|--Hashtable:底层是哈希表数据结构,是线程同步的。不可以存储null键,null值。
|--HashMap:底层是哈希表数据结构,是线程不同步的。可以存储null键,null值。替代了Hashtable.
|--TreeMap:底层是二叉树结构,可以对map集合中的键进行指定顺序的排序。
Map集合存储和Collection有着很大不同:
Collection一次存一个元素;Map一次存一对元素。
Collection是单列集合;Map是双列集合。
Map中的存储的一对元素:一个是键,一个是值,键与值之间有对应(映射)关系。
特点:要保证map集合中键的唯一性。
想要获取map中的所有元素:
原理:map中是没有迭代器的,collection具备迭代器,只要将map集合转成Set集合,可以使用迭代器了。之所以转成set,是因为map集合具备着键的唯一性,其实set集合就来自于map,set集合底层其实用的就是map的方法。
★ 把map集合转成set的方法:
Set keySet();
Set entrySet();//取的是键和值的映射关系。
Entry就是Map接口中的内部接口;
为什么要定义在map内部呢?entry是访问键值关系的入口,是map的入口,访问的是map中的键值对。
---------------------------------------------------------
取出map集合中所有元素的方式一:keySet()方法。
可以将map集合中的键都取出存放到set集合中。对set集合进行迭代。迭代完成,再通过get方法对获取到的键进行值的获取。
Set keySet = map.keySet();
Iterator it = keySet.iterator();
while(it.hasNext()) {
Object key = it.next();
Object value = map.get(key);
System.out.println(key+":"+value);
}
-------------------------------------------------------
取出map集合中所有元素的方式二:entrySet()方法。
Set entrySet = map.entrySet();
Iterator it = entrySet.iterator();
while(it.hasNext()) {
Map.Entry me = (Map.Entry)it.next();
System.out.println(me.getKey()+"::::"+me.getValue());
}
--------------------------------------------------------
使用集合的技巧:
看到Array就是数组结构,有角标,查询速度很快。
看到link就是链表结构:增删速度快,而且有特有方法。addFirst; addLast; removeFirst(); removeLast(); getFirst();getLast();
看到hash就是哈希表,就要想要哈希值,就要想到唯一性,就要想到存入到该结构的中的元素必须覆盖hashCode,equals方法。
看到tree就是二叉树,就要想到排序,就想要用到比较。
比较的两种方式:
一个是Comparable:覆盖compareTo方法;
一个是Comparator:覆盖compare方法。
LinkedHashSet,LinkedHashMap:这两个集合可以保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。
集合什么时候用?
当存储的是一个元素时,就用Collection。当存储对象之间存在着映射关系时,就使用Map集合。
保证唯一,就用Set。不保证唯一,就用List。
Collections:它的出现给集合操作提供了更多的功能。这个类不需要创建对象,内部提供的都是静态方法。
Collection 和 Collections的区别:
Collections是个java.util下的类,是针对集合类的一个工具类,提供一系列静态方法,实现对集合的查找、排序、替换、线程安全化(将非同步的集合转换成同步的)等操作。
Collection是个java.util下的接口,它是各种集合结构的父接口,继承于它的接口主要有Set和List,提供了关于集合的一些操作,如插入、删除、判断一个元素是否其成员、遍历等。
Arrays:
用于操作数组对象的工具类,里面都是静态方法。
关于集合内部的方法,这里就不介绍了,API中都有。
十一:IO流:用于处理设备上的数据。
相关概念:
重要知识点:
- FileReader fr = new FileReader("demo.txt");
- int ch = 0;
- while((ch=fr.read)!=-1){
- System.out,println((cahr)ch);
- }
- fr.close();
- FileReader fr = new FileReader("demo.txt")
- char[] buff = new char[1024]; //自定义的缓冲区
- int len = 0;
- while((len=fr.read(buff))!=-1){
- System.out.println(buff,0,len);
- }
- fr.close();
IO流体系:
字符流:
Reader:用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。
|---BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
|---LineNumberReader:跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
|---InputStreamReader:是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
|---FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。
|---CharArrayReader:
|---StringReader:
-------------------------------------------------
Writer:写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。
|---BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
|---OutputStreamWriter:是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
|---FileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。
|---PrintWriter:
|---CharArrayWriter:
|---StringWriter:
---------------------------------
字节流:
InputStream:是表示字节输入流的所有类的超类。
|--- FileInputStream:从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。
|--- FilterInputStream:包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。
|--- BufferedInputStream:该类实现缓冲的输入流。
|--- ObjectInputStream:
|--- PipedInputStream:
-----------------------------------------------
OutputStream:此抽象类是表示输出字节流的所有类的超类。
|--- FileOutputStream:文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。
|--- FilterOutputStream:此类是过滤输出流的所有类的超类。
|--- BufferedOutputStream:该类实现缓冲的输出流。
|--- PrintStream:
|--- DataOutputStream:
|--- ObjectOutputStream:
|--- PipedOutputStream:
--------------------------------
缓冲区是提高效率用的,给谁提高呢?
BufferedWriter:是给字符输出流提高效率用的,那就意味着,缓冲区对象建立时,必须要先有流对象。明确要提高具体的流对象的效率。
- FileWriter fw = new FileWriter("bufdemo.txt");
- BufferedWriter bufw = new BufferedWriter(fw);//让缓冲区和指定流相关联。
- for(int x=0; x<4; x++){
- bufw.write(x+"abc");
- bufw.newLine(); //写入一个换行符,这个换行符可以依据平台的不同写入不同的换行符。
- bufw.flush();//对缓冲区进行刷新,可以让数据到目的地中。
- }
- bufw.close();//关闭缓冲区,其实就是在关闭具体的流。
-----------------------------
BufferedReader:
- FileReader fr = new FileReader("bufdemo.txt");
- BufferedReader bufr = new BufferedReader(fr);
- String line = null;
- while((line=bufr.readLine())!=null){ //readLine方法返回的时候是不带换行符的。
- System.out.println(line);
- }
- bufr.close();
流一些总结:
流对象:其实很简单,就是读取和写入。但是因为功能的不同,流的体系中提供N多的对象。那么开始时,到底该用哪个对象更为合适呢?这就需要明确流的操作规律。
流的操作规律:
1,明确源和目的。
数据源:就是需要读取,可以使用两个体系:InputStream、Reader;
数据汇:就是需要写入,可以使用两个体系:OutputStream、Writer;
2,操作的数据是否是纯文本数据?
如果是:数据源:Reader
数据汇:Writer
如果不是:数据源:InputStream
数据汇:OutputStream
3,虽然确定了一个体系,但是该体系中有太多的对象,到底用哪个呢?
明确操作的数据设备。
数据源对应的设备:硬盘(File),内存(数组),键盘(System.in)
数据汇对应的设备:硬盘(File),内存(数组),控制台(System.out)。
4,需要在基本操作上附加其他功能吗?比如缓冲。
如果需要就进行装饰。
转换流特有功能:转换流可以将字节转成字符,原因在于,将获取到的字节通过查编码表获取到指定对应字符。
转换流的最强功能就是基于 字节流 + 编码表 。没有转换,没有字符流。
发现转换流有一个子类就是操作文件的字符流对象:
InputStreamReader
|--FileReader
OutputStreamWriter
|--FileWrier
想要操作文本文件,必须要进行编码转换,而编码转换动作转换流都完成了。所以操作文件的流对象只要继承自转换流就可以读取一个字符了。
但是子类有一个局限性,就是子类中使用的编码是固定的,是本机默认的编码表,对于简体中文版的系统默认码表是GBK。
FileReader fr = new FileReader("a.txt");
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"gbk");
以上两句代码功能一致,
如果仅仅使用平台默认码表,就使用FileReader fr = new FileReader("a.txt"); //因为简化。
如果需要制定码表,必须用转换流。
转换流 = 字节流+编码表。
转换流的子类File = 字节流 + 默认编码表。
十二:网络编程。
相关概念:
1.逻辑端口:用于表示进程的逻辑地址,不同的进程的标识;有效进程:0~65535,其中0~1024是系统使用或者保留端口2.物理端口:指的是主机或者其他设备上提供的外接接口。
Java中的IP对象 InetAddress.
Socket套接字,通信的端点:就是为网络服务提供的一种机制,通信两端都有Socket,网络通信其实就是端口Socket间的通信,数据在两个Socket之间通过IO传输
应用层的主要协议和方式有两张:UDP 和 TCP 两种.
1.只要进行网络传输,必须需要Socket套接字。
2.数据一定要封装到数据包中,数据包中包含IP地址,端口号,数据等信息。
Java中封装操作UDP来进行网络通信的主要类是DatagramSocket对象以及DatagramPacket(数据包)。
DatagramSocket:具备接受和发送功能,但进行传输时,需要明确发送端和接收端。
DatagramPacket:数据包对象,用于操作数据包中的各种信息。
UDP传输发送端的步骤:
1.建立UDP的Socket服务,创建对象时如果没有声明端口,那么系统会自动分配给其一个未使用的端口号。
2.明确要发送的数据。
3.将数据封装到数据包对象中。
4.用Socket的Send方法将数据包发送出去。
5.关闭资源(必须记得做)
下面给出一个例子作为参考:
- class UdpSend{
- public static void main (String[] args){
- //1.使用DatagramSocket来建立UDP的Socket服务
- DatagramSocket ds = new DatagramSocket(8088);//指定发送端的端口8088,如果不指定自动默认分配
- //2.明确要发送的具体数据
- String context = "发送一段UDP信息。";
- byte[] buff = context.getBytes();
- //3.将数据封装到要发送的数据包中
- DatagramPacket dp = new DatapramPacket(buff,buff.length,InetAddress.getName("192.168.0.112"),10000);//要将该信息发往指定主机的10000端口上
- //4.使用Socket的send方法,将数据包发送出去。
- ds.send(dp);
- //5.关闭资源
- ds.close();
- }
- }
UDP传输接受端的步骤:
1.建立UDP的Socket服务,明确一个端口,作用在于,只有发送到这个端口的数据才是这个接受端可以接受处理的数据
2.创建数据包对象用于接受(存储)数据包。
3.利用Socket服务的接受方法将收到的数据存储到数据包中。
4.通过数据包对象获取数据包中的具体内容,如ip地址,端口,数据等。
5.关闭资源(必须做)
接受端的例子:
- class UdpReceive{
- public static void main(String[] args){
- //1.使用DatagramSocket建立UDP的Socket服务。
- DatagramSocket ds = new DatagramSocket(10000);//设置端口,声明接受该端口的数据
- //2.创建数据包对象,创建接受存收到的数据。(需要先定义字节数组,数据包会将接受到的数据存入到字节数组中)
- byte[] buff = new byte[1024];
- DatagramPacket dp = new DatagramPacket(buff,buff.length);
- //3.利用Socket服务,接受发送过来的数据包
- ds.receive(dp);//该方法是阻塞式方法,没有监听到有数据发送过来的时候,会一直等待。
- //4.通过数据包对象的方法获取数据包中信息
- String ip = dp.getAddress.getHostAddress();
- int port = dp.getPort();
- String context = new String(dp.getData(),0,dp.length);
- System.out.println("ip:"+ip+" port:"+port+" context:"+context);
- //5.关闭资源
- ds.close();
- }
- }
- class TcpClient{
- public static void main(String[] args){
- Socket s = new Socket("192.168.1.112",10002);
- OutputStream out = s.getOutputStream(); //获取了Socket流中的输出流对象。
- out.write("TCP连接。。。".getBytes());
- s.close();
- }
- }
- class TcpServer{
- public static void main(String[] args) throws Exception{
- ServerSocket ss = new ServerSocket(10002); //建立服务端的Socket服务
- Socket s = ss.accept(); //获取客户端对象
- String ip = s.getInetAddress().getHostAddress();
- System.out.println(ip+“.....connection”);
- //可以通过获取到的Socket对象中的Socket流和具体的客户端进行通讯
- InputStream in = s.getInputStream(); //读取客户端的数据,使用客户端对象的Socket读取流
- byte[] buff = new byte[1024];
- int len = in,read(buff);
- String text = new String(buff,0,len);
- System.out.println(text);
- //关闭资源,注意一定是先关客户端,再关闭服务端
- s.close();
- ss.close();
- }
- }
网络编程中的URLEncoder和URLDecoder.
URLEncoder类的encode()静态方法:是将一个普通的字符串转化为一个百分号编码格式字符串。
URLDecoder类的decode()静态方法:是将百分号编码格式字符串转化为一个普通的字符串。
URL与URLConnection对象:前者是表示应用程序和URL之间的通信连接,后者表示与URL之间的HTTP连接。程序可以通过URLConnection实例向该URL发生请求,读取URL引用的资源。