java基础知识02

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
.cn 域名,1个 12个月
简介: 接着《java基础知识01》,再来聊聊剩下的那些知识点。

一、java基础类库:


1、String字符串:


字符串一旦被初始化,就不可以被改变,存放在方法区中的常量池中。用length()方法获取长度。


2、StringBuffer字符串缓冲区:


特点:


  • 可以对字符串内容进行修改。
  • 是一个容器。
  • 是可变长度的。
  • 缓冲区中可以存储任意类型的数据。
  • 最终需要变成字符串。


容器通常具备一些固定的方法:append()、insert()、delete()、replace()等。


3、StringBuilder字符串缓冲区:


JDK1.5出现StringBuiler;与StringBuffer区别如下:


  • StringBuffer线程安全,StringBuilder线程不安全。
  • 单线程操作,使用StringBuilder 效率高。多线程操作,使用StringBuffer 安全。


4、包装类:


注意int ---> Integer 和 char ---> Character,这两个基本类型对应的包装类不是首字母大写就可以,其他的对应的包装类都是首字母大写,注意区分。


5、Collections:


操作集合的工具类,提供了大量的操作集合的方法,十分方便,且方法都是静态方法。


6、Arrays:


操作数组的工具类,提供了大量的操作数组的方法,里面的也都是静态方法。看下面这个常用方法:


asList方法:将数组转换成list集合。

String[] arr = {"abc","kk","qq"};
List<String> list = Arrays.asList(arr);// 将arr数组转成list集合。


二、集合:


1、集合和数组的区别:


  • 数组是固定长度的;集合可变长度的。
  • 数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。
  • 数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型。


image.png


2、Set集合:


无序(存入和取出顺序有可能不一致),不可以存储重复元素,必须保证元素唯一性。它的各个实现的特点如下:


  • HashSet:底层数据结构是哈希表,线程是不同步的。无序,高效;HashSet集合通过元素的hashCode方法和equals方法保证元素的唯一性。当元素的hashCode值相同时,才继续判断元素的equals是否为true。如果为true,那么视为相同元素,不存。如果为false,那么存储。如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。
  • LinkedHashSet:有序,hashset的子类。
  • TreeSet:对Set集合中的元素的进行指定顺序的排序,排序需要依据元素自身具备的比较性,如果元素不具备比较性,在运行时会发生ClassCastException异常。线程不同步。TreeSet底层的数据结构就是二叉树。


3、List集合:


有序(元素存入集合的顺序和取出的顺序一致),元素都有索引。元素可以重复。它的实现有三个:


  • ArrayList:底层的数据结构是数组,线程不同步,ArrayList替代了Vector,查询元素的速度非常快。
  • LinkedList:底层的数据结构是链表,线程不同步,增删元素的速度非常快。
  • Vector:底层的数据结构就是数组,线程同步的,Vector无论查询和增删都巨慢。


4、Map集合:


以键值对形式存储元素,其各个实现的特点如下:


  • Hashtable:底层是哈希表数据结构,是线程同步的。不可以存储null键,null值。
  • HashMap:底层是哈希表数据结构,是线程不同步的。可以存储null键,null值。替代了Hashtable。
  • TreeMap:底层是二叉树结构,可以对map集合中的键进行指定顺序的排序。


5、集合使用技巧:


  • 看到Array就是数组结构,有角标,查询速度很快。
  • 看到link就是链表结构:增删速度快,而且有特有方法:addFirst()、 addLast()、 removeFirst()、 removeLast()、 getFirst()、getLast();
  • 看到hash就是哈希表,就要想到哈希值,就要想到唯一性,就要想到存入到该结构的中的元素必须覆盖hashCode和equals方法。
  • 看到tree就是二叉树,就要想到排序,就要用到比较。
  • 如何判断使用哪个集合?存储一个元素且要保证唯一性就用Set,存储一个元素不用保证唯一性就用List,存储含有映射关系的对象就用Map。


三、IO流:


IO流就是用来处理设备上的数据的,输入和输出是以内存为参照物。InputStream,输入流,把计算机的数据输入到内存,所以是读;OutputStream,输出流,把内存中的数据输出到计算机,所以是写。


1、IO流分类:


  • 字节流(InputStream 和 OutputStream):处理字节数据的流对象。设备上的数据无论是图片、视频还是文字,它们都以二进制存储的。计算机中的最小数据单元就是字节,这就意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。
  • 字符流(Reader 和 Writer):因为每个国家的字符都不一样,所以涉及到了字符编码问题。GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时再指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。


2、IO流继承体系:


(1).字节流:


InputStream:是表示字节输入流的所有类的超类。


  • |--- FileInputStream:从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符,请考虑使用 FileReader。
  • |--- FilterInputStream:包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。
         |--- BufferedInputStream:该类实现缓冲的输入流。
         |--- Stream
  • |--- ObjectInputStream:
  • |--- PipedInputStream:


OutputStream:此抽象类是表示输出字节流的所有类的超类。


  • |--- FileOutputStream:文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。
  • |--- FilterOutputStream:此类是过滤输出流的所有类的超类。
         |--- BufferedOutputStream:该类实现缓冲的输出流。
         |--- PrintStream
         |--- DataOutputStream
  • |--- ObjectOutputStream
  • |--- PipedOutputStream


(2).字符流:


Reader:用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。


  • |--- BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

   

|---LineNumberReader:跟踪行号的缓冲字符输入流。此类定义了 setLineNumber(int)方法 和 getLineNumber()方法,它们可分别用于设置和获取当前行号。


  • |--- InputStreamReader:称为转换流,是字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
       

|--- FileReader:InputStreamReader的子类,最常用的转换流。用来读取字符文件的便捷类。


  • |--- CharArrayReader
  • |---StringReader


Writer:写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。


  • |--- BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
  • |--- OutputStreamWriter:称为转换流,是字符流通向字节流的桥梁:可使用指定的charset将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
       

 |--- FileWriter:OutputStreamWriter的子类,最常用的转换流。用来写入字符文件的便捷类。


  • |--- PrintWriter
  • |--- CharArrayWriter
  • |--- StringWriter


下面介绍几个流的用法,看下面例子:

/*创建可以读取文本文件的流对象,FileReader让创建好的流对象和指定的文件相关联。*/
  FileReader fr = new FileReader("demo.txt");
  int ch = 0;
  while((ch = fr.read())!= -1) { //条件是没有读到结尾
      System.out.println((char)ch); //调用读取流的read方法,读取一个字符。
  }
  fr.close();
  /* =======================下面这种自定义缓冲区的方式更高效=============================== */
  FileReader fr = new FileReader("demo.txt"); //创建读取流对象和指定文件关联。
  //因为要使用read(char[])方法,将读取到字符存入数组。
  //所以要创建一个字符数组,一般数组的长度都是1024的整数倍。
  char[] buf = new char[1024];
  int len = 0;
  while(( len=fr.read(buf)) != -1) {
         System.out.println(new String(buf,0,len));
  }
  fr.close();
  /* ==================================== 高效写数据 ======================================*/
  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();//关闭缓冲区,其实就是在关闭具体的流。
  /* ==================================== 高效读数据 ======================================*/
  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();


3、流的操作规律:


从上面的流体系可以看到,Java提供了很多的流供我们使用,感觉很复杂。那么使用的时候该如何选择呢?就得明确以下几点:


(1). 明确目的:


  • 读数据:使用InputStream、Reader体系
  • 写数据:使用OutputStream、Writer体系


(2). 操作的数据是否是纯文本数据?


  • 如果是:读数据:Reader;写数据:Writer
  • 若不是:读数据:InputStream;写数据:OutputStream


(3). 虽然确定了一个体系,但是该体系中有太多的对象,到底用哪个呢?


  • 从何处读取数据:硬盘(File),内存(流),键盘(System.in)
  • 把数据写到何处:硬盘(File),内存(流),控制台(System.out)


(4). 需要在基本操作上附加其他功能吗?比如缓冲。如果需要就进行装饰,那就用带Buffer的流。


(5). 凡是操作设备上的文本数据,涉及编码转换,必须使用转换流。


4、File类:


将文件系统中的文件和文件夹封装成了对象。提供了更多的属性和行为可以对这些文件和文件夹进行操作。这些是流对象办不到的,因为流只操作数据。常用方法如下:


(1). 创建:

boolean createNewFile(); //在指定目录下创建文件,如果该文件已存在,则不创建。
boolean mkdir(); //创建此抽象路径名指定的目录。
boolean mkdirs(); //创建多级目录。


(2). 删除:

boolean delete(); //删除此抽象路径名表示的文件或目录。
void deleteOnExit(); //在虚拟机退出时删除。
// 注意:在删除文件夹时,必须保证这个文件夹中没有任何内容,才可以将该文件夹用delete删除。
// java删除文件不走回收站。要慎用。


(3). 获取:

long length(); //获取文件大小。
String getName(); //返回由此抽象路径名表示的文件或目录的名称。
String getPath(); //将此抽象路径名转换为一个路径名字符串。
String getAbsolutePath(); //返回此抽象路径名的绝对路径名字符串。
String getParent(); //返回此抽象路径名父目录的抽象路径名,如果此路径名没有指定父目录,则返回 null。
long lastModified(); //返回此抽象路径名表示的文件最后一次被修改的时间。
File.pathSeparator; //返回当前系统默认的路径分隔符,windows默认为 “;”。
File.Separator; //返回当前系统默认的目录分隔符,windows默认为 “\”。


(4). 判断:

boolean exists();// 判断文件或者文件夹是否存在。
boolean isDirectory(); //测试此抽象路径名表示的文件是否是一个目录。
boolean isFile(); //测试此抽象路径名表示的文件是否是一个标准文件。
boolean isHidden(); //测试此抽象路径名指定的文件是否是一个隐藏文件。
boolean isAbsolute(); //测试此抽象路径名是否为绝对路径名。


(5). 重命名:

boolean renameTo(File dest); //可以实现移动的效果。剪切+重命名。


(6). String[] list():列出指定目录下的当前的文件和文件夹的名称。包含隐藏文件。


如果调用list方法的File 对象中封装的是一个文件,那么list方法返回数组为null。如果封装的对象不存在也会返回null。只有封装的对象存在并且是文件夹时,这个方法才有效。


四、网络编程:


所谓网络编程,其实可以简单的理解为就是在两个或两个以上的设备之间传输数据。


1、相关概念:


  • IP:为了能够识别接入互联网的每个设备,网络中的每个设备都会有一个唯一的数字标识,这个标识就是IP。就像手机号用来标识不同的手机用户一样。每个计算机在联网后都有一个唯一的合法IP地址。
  • 域名:由于IP地址是一串数字不方便记忆,所以为了方便记忆就有了域名这个概念。就像手机号码不方便记忆,你会设置备注一样。一个IP地址可以对应多个域名,一个域名只能对应一个IP。
  • DNS服务器:上面说了,IP是联网计算机的唯一标识,但是使用的时候我们又会用域名代替IP,所以在实际传输数据前需要将域名转换为IP地址。实现将域名解析为IP地址的服务器就叫DNS服务器。所以我们在地址栏请求某个域名时,首先请求的是DNS服务器。
  • 端口:IP和域名就能很方便的在网络中找到该IP对应的计算机,但是一个计算机可以同时运行多个网络程序,为了区分每个程序,就引入了端口这个概念。IP是区分不同的计算机的,端口就是区分同一台电脑上不同的应用程序的。有效端口:0 ~ 65535,其中0 ~1024系统使用或保留端口。


有了IP + 端口,就可以标识唯一的一台计算机上的一个唯一的程序了。但是网络程序之间还需要进行数据交换,所以还需要了解网络通讯。


  • 网络通讯:可以理解为就是不同计算机之间进行数据交换。网络通讯基于“请求-响应”模型。所谓的“请求-响应”模型,就是一问一答都形式,一端请求,另一端就响应,不请求就不会有响应。
  • 客户端(client):在网络通讯中,主动发起通讯的程序被称作客户端程序,简称客户端。
  • 服务器(server):而在一次网络通讯中等待连接的程序叫做服务器端程序,简称服务器。


这样的网络编程结构被称作客户端/服务器结构,简称C/S结构。这种结构的程序通用性差,一个程序的客户端只能和与之对应的服务器通讯,而不能和其他服务器通讯。我们还有另一种方式,就是使用浏览器作为通用客户端与服务器进行通讯,这种使用浏览器作为客户端的结构称作浏览器/服务器结构,简称B/S结构


  • 协议:这是网络编程中最重要也是最复杂的一个概念。网络编程就是运行在不同计算机中的两个程序之间的数据交互。但是计算机毕竟不是人脑,接收到的数据它也无法理解。为了让计算机能理解接收的数据,就需要规定该数据的格式,这个数据的格式就叫做协议。就比如发送电报,先按照某种规则加密,另一端接收到的是加密后的电报,想要知道电报内容,就得按照规则解密,这种规则就叫协议。协议格式是随便编写的,只要按照这种格式能生成唯一的编码,另一端能唯一的解析出数据的内容即可。也正是这个原因,导致客户端只能和与之对应的服务器通讯。
  • 网络通讯方式:TCP和UDP方式。TCP方式建立专门的虚拟连接,进行可靠的数据传输,所以重要的数据一般采用这种方式传输;而UDP方式不需要建立虚拟连接,数据传输不可靠。


2、 网络编程步骤:


(1). 客户端网络编程步骤:


  • 建立网络连接
  • 交换数据
  • 关闭网络连接


(2). 服务端网络编程步骤:


  • 监听端口
  • 获得连接
  • 交换数据
  • 关闭连接


3、Java网络编程:


和网络编程相关的API位于java.net包下。


(1). 部分相关API如下:


  • InetAddress:java 中ip对象
  • Socket:套接字,通信的端点。就是为网络服务提供的一种机制,通信的两端都有Socket,网络通信其实就是Socket间的通信,数据在两个Socket间通过IO传输。
  • DatagramPacket:通过这个对象中的方法,就可以获取到数据包中的各种信息。
  • DatagramSocket.:封装了udp传输协议的socket对象。


(2). UDP方式案例:


客户端:

public static void main(String[] args)throws Exception {
        //1,建立udp的socket服务。
        DatagramSocket ds = new DatagramSocket(8888);//指定发送端口,不指定系统会随机分配。
        //2,明确要发送的具体数据。
        String text = "演示udp传输";
        byte[] buf = text.getBytes();
        //3,将数据封装成了数据包。
        DatagramPacket dp = new DatagramPacket(buf,
                                 buf.length,InetAddress.getByName("10.1.31.127"),10000);
        //4,用socket服务的send方法将数据包发送出去。
        ds.send(dp);
        //5,关闭资源。
        ds.close();
    }


服务端:

public static void main(String[] args) throws Exception{
        //1,创建udp的socket服务。
        DatagramSocket ds = new DatagramSocket(10000);
        //2,定义数据包,用于存储接收到数据。先定义字节数组,数据包会把数据存储到字节数组中。
        byte[] buf = new byte[1024];
        DatagramPacket dp = new DatagramPacket(buf,buf.length);
        // 3,通过socket服务的接收方法将收到的数据存储到数据包中。
        ds.receive(dp);//该方法是阻塞式方法。
        // 4,通过数据包的方法获取数据包中的具体数据内容,比如ip,端口,数据等等。
        String ip = dp.getAddress().getHostAddress();
        int port = dp.getPort();
        String text = new String(dp.getData(),0,dp.getLength());//将字节数组中的有效部分转成字符串。
        System.out.println(ip+":"+port+"--"+text);
        // 5,关闭资源。
        ds.close();
    }


(3). TCP方式案例:


客户端:

public static void main(String[] args) throws Exception{
        Socket s = new Socket("10.1.31.69",10002);
        OutputStream out = s.getOutputStream();//获取了socket流中的输出流对象。
        out.write("tcp演示".getBytes());
        s.close();
}


服务端:

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+".....connected");
        //可以通过获取到的socket对象中的socket流和具体的客户端进行通讯。
        InputStream in = s.getInputStream();//读取客户端的数据,使用客户端对象的socket读取流
        byte[] buf = new byte[1024];
        int len = in.read(buf);
        String text = new String(buf,0,len);
        System.out.println(text);
        //如果通讯结束,关闭资源。注意:要先关客户端,在关服务端。
        s.close();
        ss.close();
    }


总结:


《java基础知识01》和本文简陋的总结了一些java基础的知识点,由于本人只是个小白,只能在此抛砖引玉,望各位大神多多指点!




相关文章
|
3月前
|
Java
【Java基础】输入输出流(IO流)
Java基础、输入输出流、IO流、流的概念、输入输出流的类层次结构图、使用 InputStream 和 OutputStream流类、使用 Reader 和 Writer 流类
132 2
|
5天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
3月前
|
安全 Java
|
3月前
|
安全 Java 编译器
杭州 【Java基础知识 11】java泛型方法的定义和使用(学习+改进+自己理解,想法) (借鉴-侵-删)
杭州 【Java基础知识 11】java泛型方法的定义和使用(学习+改进+自己理解,想法) (借鉴-侵-删)
32 1
|
3月前
|
搜索推荐 算法 Java
【Java基础】 几种简单的算法排序
几种简单的JAVA算法排序
41 4
|
4月前
|
Java 调度 开发者
Java中的多线程编程:基础知识与实践
【5月更文挑战第29天】 在现代软件开发中,多线程编程是一个不可忽视的领域。特别是在Java这种广泛使用的编程语言中,掌握多线程的概念和技术对于开发高效、响应迅速的应用程序至关重要。本文将深入探讨Java多线程的核心概念、实现机制以及常见问题的解决方案。我们将从基础出发,逐步揭示如何通过多线程提升程序性能,并且讨论并发编程中的挑战和解决策略。文章的目的是为开发者提供一个清晰的多线程编程指南,帮助他们在实际项目中有效地应用这些知识。
29 3
|
4月前
|
Java 开发者
Java中的多线程编程:基础知识与实践
【5月更文挑战第26天】 在现代计算机科学中,多线程编程是一个复杂且强大的概念。Java作为一种广泛使用的编程语言,其对多线程的支持使得开发者能够创建出更为复杂、高效和响应迅速的应用程序。本文将深入探讨Java中的多线程编程,从基础概念到实际编程技巧,为读者提供全面的理解和实践指导。
|
4月前
|
监控 IDE Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第30天】 在现代软件开发中,多线程编程是提高应用程序性能和响应能力的关键。特别是在Java这样的多平台、多用途的编程语言中,掌握多线程技术至关重要。本文旨在为读者提供有关Java多线程编程的全面介绍,从基本概念到高级应用技巧,帮助初学者和有经验的开发者理解并有效使用多线程。文章不仅涉及基础理论,还包括代码示例和最佳实践,确保读者能够将知识应用于实际项目中。
|
4月前
|
Java 程序员 调度
Java中的多线程编程:基础知识与实践
【5月更文挑战第28天】 在现代计算机科学中,多线程编程是一个重要的概念,它允许程序同时执行多个任务。在Java中,多线程编程是通过创建并管理线程来实现的。本文将介绍Java中多线程编程的基础知识,包括线程的概念、创建和控制线程的方法,以及线程同步和通信的相关技术。通过阅读本文,读者将对Java中的多线程编程有一个全面的了解,并能在实际编程中应用这些知识。
|
4月前
|
安全 Java 数据安全/隐私保护
Java中的多线程编程:基础知识与实践
【5月更文挑战第24天】 在现代软件开发中,多线程编程是提升应用性能和响应速度的关键技术之一。Java 作为一种广泛使用的编程语言,其内置的多线程功能为开发者提供了强大的并发处理能力。本文将深入探讨 Java 多线程的基础概念、实现机制以及在实际开发中的应用。我们将从线程的创建和管理出发,逐步讲解同步机制、死锁问题以及如何利用高级并发工具有效地构建稳定、高效的多线程应用。通过理论结合实例的方式,旨在帮助读者掌握 Java 多线程编程的核心技能,并在实际项目中灵活运用。