当前位置:网站首页 > Java基础 > 正文

渝中java基础



目录

String字符串

定义

字符串对象的含义

关于字符串对象内存地址的问题

1.使用“”赋值创建字符串对象

2.通过构造方法创建字符串对象

3.使用+拼接""和new出来的字符串对象创建字符串对象 (难点)

比较字符串时为什么要使用equals方法而不用“==”

两者比较的本质

使用equals方法的注意点

可变字符串

使用StringBuilder和StringBuffer时的注意点

可变字符串相关面试题

方法调用的传值问题

与八大原始类型对应的包装类

异常

方法

try-catch-finally

try-catch-finally相关面试题

throws关键字

 数组和集合的区别

泛型

集合家族

Collection接口

常用方法

lterable接口为什么不是集合的根接口

Collections集合工具类

list接口

实现类接口-ArrayList接口

实现类接口-LinkedList接口

set接口

实现接口-HashSet接口

实现接口-TreeSet接口

 特点

集合和数组之间的转换

Map接口 

实现类-HashMap接口

遍历集合中元素的方式

数组管理系统 VS 集合管理系统

使用数组完成-ATM系统

使用(List集合)ArrayList实现-新闻管理系统

使用(Map集合)HashMap实现-用户管理系统

文件类File

IO

流Stream

使用FileInputStream和FileOutputStream实现-单文件的复制

文件夹的复制

序列化和反序列化应用

网络编程

InetAddress类

Socket类和ServerSocket类

使用套接字对象实现两个端点(Socket和ServerSocket)之间发送文件

进程和线程

并行和并发 

同步和异步

Java中的线程Thread类 

实现多线程

生命周期 

守护线程

多线程访问同一个资源 

死锁

多线程相关面试题 

个人总结


String字符串


定义

是一个属于数据类型的引用类型,本质是一个类。

字符串对象的含义

使用“”引起来的内容

关于字符串对象内存地址的问题

1.使用“”赋值创建字符串对象

 

说明:

  • 第一段语句:创建了“Java”的字符串对象,确实将这个字符串对象的地址保存在了变量name中。(在字符串常量池中没找到“Java”字符,就会创建一个新的“Java”字符串对象)
  • 第二段语句:表面上是重新给name变量赋了值,实质是创建了新的“OK”字符串对象。(过程就是执行时,发现“OK”在字符串常量池中不存在,就会创建一个新的“OK”字符串对象)
  • 第三段语句:表面上创建了新的字符串对象,其实是直接引用“Java”字符对象(这时它已经在常量池中找到了,所以就直接使用。)
  • 第四段语句:+两端都是""定义的字符串,值得注意的是:它是在拼接后再判断字符串常量池(缓冲区)中是否存在(拼接后的"Java"依然存在,将其地址保存到thing变量中)

以上变量(除却name创建新的“OK”字符串对象)的内存地址都是相等的(用的“==”做判断)

2.通过构造方法创建字符串对象

 

说明:

  • 第一段语句:在字符串常量池中寻找"Java",不存在,所以在堆中newString(),将字符串常量池中的"Java"保存到new出来的区域,最后将堆中new出来的地址保存到栈中变量str1中。
  • 第二段语句:在字符串常量池中寻找"Java",存在,直接引用,同样的在堆中newString(),将字符串常量池中的"ab"保存到new出来的区域,最后将堆中new出来的地址保存到栈中变量str2中。

 以上str1和str2的内存地址不同(用的“==”做判断)(原因:str1和str2是堆中的两个区域)

3.使用+拼接""和new出来的字符串对象创建字符串对象 (难点)

 

 说明:

  1. 创建StringBuilder对象
  2. 在字符串常量池中创建"Ja"
  3. 在字符串常量池中创建"va"
  4. 创建String对象,保存"va"的地址
  5. 调用StringBuilder的append方法,将"Ja"和newString("va")拼接

以上过程一共创建4个对象("Ja","va",String, StringBuilder对象)

比较字符串时为什么要使用equals方法而不用“==”

两者比较的本质

  • “==”判断的是内存地址
  • 使用String类重写的equals方法进行判断,就是将两个字符串用字符数组保存,逐个判断字符数组中的每个字符,全部一致时返回true,所以比较的是字面值。

使用equals方法的注意点

要将已知不为空的字符串作为调用者,才不会出现空指针异常的问题。

可变字符串

使用StringBuilder和StringBuffer时的注意点

  • 普通方法都是在直接操作同一个字符串对象,每次调用方法后,原字符串都会发生变化
  • StringBuffer和StringBuilder并没有重写equals方法,所以可变字符串的值是否相同时,调用的是equals中原始的==判断。如果要判断两个可变字符串的值是否相同时,需要将其转换为String后调用equals判断

可变字符串相关面试题

比较String,StringBuilder和StringBuffer的区别

  • 相同点
  • 都可以表示字符串。都提供了一些操作字符串的方法。
  • 都有相同的方法,如charAt()、indexOf等。
  • 都是被final修饰的类,不能被继承。
  • 不同点
  • String定义的字符串是一个常量,可变字符串定义的字符串是一个变量。
  • String类中的方法,调用后,不会改变原本字符串的值;可变字符串类中的方法,调用后,会改变原本字符串的值。
  • StringBuilder是非线程安全的可变字符串类,StringBuffer是线程安全的可变字符串类,其中的方法被synchronized修饰。
渝中java基础
  • 总结

在频繁操作同一个字符串时,一定要使用可变字符串StringBuidler或StringBuffer类的对象,不能使用String类的对象。

方法调用的传值问题

只有参数是引用类型(类,数组,接口),在方法中是直接操作该参数,才会对实际参数造成影响。(引用类型如果在方法中再创建新对象则不会对实际参数造成影响)

与八大原始类型对应的包装类

包装类原始类型BytebyteShortshortIntegerintLonglongFloatfloatDoubledoubleCharactercharBooleanboolean

异常

方法

try-catch-finally

原理

注意点 

  • try、catch、finally都不能单独使用,try需要配合catch或finally或catch和finally一起使用。
  • 执行try中的内容时,当某行代码抛出异常,不再执行try中该行代码后续的内容。
  • 无论try中的代码是否会抛出异常,finally中的代码一定会执行。
  • 如果代码会抛出多个异常,可以使用多个catch进行捕获,需要将异常子类放在最前,异常父类放在最后。
  • 如果代码会抛出多个异常,可以使用多个catch进行捕获,需要将异常子类放在最前,异常父类放在最后。
  • 在try中定义的内容,无法在try之外的地方使用。
  • try中如果有return,不影响finally的执行,finally优先于return执行。

try-catch-finally相关面试题

final、finally、finalize的区别

  • final是一个修饰符,被final修饰的属性称为常量,方法不能被重写,类不能被继承。
  • finally是try-catch-finally结构中的关键字,在无论是否抛出异常,都会执行的代码块。
  • finalize是Object类中的方法,finalize()在某个对象被回收前调用的方法。

throws关键字

throw和throws的区别

  •     throws表示用于声明方法有可能出现的异常。使用时写在方法的小括号之后。
  •     throw用于手动抛出异常对象。使用时,写在方法体中,常用于满足某种情况时,强制中断程序用法:throw异常对象。

 数组和集合的区别

数组的特点

  •         数组中保存的元素都是有序的。可以通过下标快速访问。
  •         数组中保存的数据都是同一种类型。
  •         数组的长度在定义后,无法改变。
  •         数组无法获取其中保存的元素实际数量。

 集合的特点

  •         能保存一组数据,可以有序也可以无序。
  •         集合的容量可变。
  •         集合中可以保存不同类型的数据。
  •         可以获取集合中保存的元素实际数量。

泛型

定义

一种规范,常用于限制集合中元素的类型,省去遍历元素时判断是否为对应类型和转型的过程

用法

在定义集合遍历时,在类后面写上<引用数据类型>
集合类或接口<引用数据类型> 集合变量名= new集合实现类();

 

集合家族

Collection接口

常用方法

方法名返回值作用add(Object obj)boolean将元素添加到集合中size()int获取集合中的元素数量isEmpty()boolean判断集合是否为空clear()clear()清空集合contains(Object obj)boolean判断集合中是否存在指定元素remove(Object obj)boolean移除集合中的指定元素toArray()Object[]将集合转换为数组iterator()iterator获取集合的迭代器对象,用于遍历集合

lterable接口为什么不是集合的根接口

原因

  • lterable被称为迭代器,是用于遍历集合元素的一个工具接口。

Collections集合工具类

与Collection的区别

  • Collection是集合的根接口,定义了集合操作元素的方法。
  • Collections是集合的工具类,定义了集合操作元素的静态方法。

常用方法

方法名作用Collections.shuffle(List list)打乱集合中的元素顺序(洗牌)Collections.swap(List list,int a,int b)交换集合中的元素位置,参数为集合和两个索引Collections.replaceAll(List list,Object obj,Object obj)替换集合中的旧元素为新元素Collections.sort(List list)对集合中的元素进行排序,根据集合中元素的类的compareTo()方法排序Collections.reverse(List[] list)翻转集合中的元素

list接口

特点

  • 有序可重复
  • 可以根据索引进行删除、获取元素等

实现类接口-ArrayList接口

特点

  • 采用数组实现的集合。
  • 可以通过索引访问元素,可以改变集合大小,如果要在其中插入和删除元素时,会影响后续元素。
  • 该集合中保存的都是引用类型。
  • 该集合查询效率高,中途增加和删除元素效率低。

构造方法

常用构造方法名·说明ArrayList()创建一个Object类型的空数组。在调用添加方法后,该数组大小为10ArrayList(int initialCapacity)创建一个指定容量的Object数组,如果参数为负,会抛出IllegalArgumentException异常

常用方法实现了Collection接口和List接口。

实现类接口-LinkedList接口

特点

  • 采用双向链表实现的集合。
  • 集合中保存的每个元素也称为节点,除首尾节点外,其余节点都保存了自己的信息外,还保存了其前一个和后一个节点的地址。
  • 如果在双向链表的数据结构中插入和删除操作节点时,不会影响其他节点的位置。如添加时新节点时,只需要重写定义新节点的前后节点位置即可。
  • 如果要查询某个节点时,需要从头结点或尾结点开始一步步得到目标节点的位置。
  • 双向链表在中间插入和删除的效率高,随机读取的效率低。

构造方法

常用构造方法名说明LinkedList() 创建一个空链表

常用方法不仅实现了Collection接口和List接口,还实现了Deque接口的方法。

set接口

特点

  • 无序不重复。
  • 允许保存null,没有索引。
  • 没有自己定义的方法,都是继承于Collection接口中的方法。

 哈希表(set集合实现原理)

  • 哈希表,也称为散列表,是—种数据结构,能更快地访问数据。
  • 要保存的数据称为原始值,这个原始值通过一个函数得到一个新的数据,这个函数称为哈希函数,这个新数据称为哈希码,哈希码和原始值之间有一个映射关系,这个关系称为哈希映射,可以构造一张映射表,这个表称为哈希表。在哈希表中,可以通过哈希码快速地访问对应的原始值。
  • 哈希冲突,多出现在哈希函数有一定的几率让多个原始值得到相同的哈希码(哈希码一致,实际值不同)。
  • 值得注意的是,如果两个对象的hashCode不同,这两个对象一定不同。如果两个对象的hashCode相同,这两个对象不—定相同。(此处就可能出现哈希冲突)
  • 解决哈希冲突,就要使用"拉链法",将重复的这个哈希码所在的位置向链表—样进行延伸。

实现接口-HashSet接口

特点

  • 采用哈希表实现。
  • 元素不能重复,无序保存,允许保存null。
  • 本质是一个HashMap对象。
  • 使用HashSet集合时,通常要重写实体类中的equals和hashcode方法。

 常用方法没有属于自定义的方法,都是重写了父接口Set和Collection中的方法。(注意没有与索引相关的方法。)

添加数据原理

  • 如果两个的hashCode相同且equals结果为true,视为同一个对象,不能添加。
  • 每次向集合中添加元素时,先判断该元素的hashCode是否存在:
        如果不存在,视为不同对象,直接添加;
        如果存在,再判断equals方法的结果(如果false,视为不同对象,可以添加;如果true,视为同一对象,不能添加)

 equals方法和hashCode的关系

  • 如果没有重写equals,默认是Object中使用==判断,如果结果为true,说明是同一个对象,hashCode一定相同。
  • hashCode不同,说明不是同一个对象,没有重写equals,说明使用Object中equals的==判断,结果为false。
  • 如果两个对象的hashCode相同,equals方法的比较结果为:可能是true(同一地址),可能是false(哈希冲突)。

实现接口-TreeSet接口

 特点

  • 特殊的Set实现类,数据可以有序保存,可以重复,不能添加null。
  • 采用红黑树(自平衡二叉树实现的集合。
  • 只能添加同一种类型的对象且该类实现了Comparable接口。
  • compareTo()方法的返回值决定了能否添加新元素和新元素的位置。
  • 添加的元素可以自动排序。

构造方法 

常用构造方法名说明TreeSet()创建一个空集合,实际上是创建了一个 TreeMap对象。

使用场景

  • 如果要保存的元素需要对其排序,使用该集合。
  • 保存在其中的元素必须要实现Comparable接口,且重写compareTo()方法,自定义排序规则。

集合和数组之间的转换

集合转换为数组

使用Collection接口中的toArray()方法。

 

数组转换为集合

遍历数组的同时添加到集合中。

 

一组数据转换为集合

使用Arrays工具类中的asList(一组数据)方法。

 

Map接口 

特点

  • Map成为映射,数据以键值对的形式保存。
  • 键称为Key,值称为Value,键不能重复,键允许出现一个null作为键,值无限制。
  • 键和值都是引用类型。

常用方法

方法名作用size()得到键值对的数量clear()清空所有键值对put(Object key,Object value)向集合中添加一组键值对get(Object key)在集合中根据键得到对应的值remove(Object key)/remove(Object key,Object key)根据键或键值对移除keyset()获取键的集合values()获取值的集合containsKey(Object key)判断是否存在某个键containsValue(Object value)判断是否存在某个值entrySet()得到集合中的所有键值对

实现类-HashMap接口

构造方法

常用构造方法名说明HashMap()创建一个空的映射集合,默认大小为16,加载因子为0.75

常用方法继承自Map。

遍历集合中元素的方式

遍历List集合

 

方式一:普通for循环

 

方式二:增强for循环

 

方式三:迭代器

 

遍历Set集合

 

方式一:增强for循环

 

方式二:迭代器

 

遍历Map集合

 

方式一:根据键得到对应的值

 

方式二:遍历键值对

 

数组管理系统 VS 集合管理系统

使用数组完成-ATM系统

User类(封装的用户类)

 

Bill类(封装的账单类)

 

自定义异常类-MoneyException类(取多抛出的异常)

 

自定义异常类-passwordException类(密码多次错误抛出的异常)

 

ATM类(主要方法集合)(注意整个过程返回对象之后,就会一直直接操作此对象,所有不需要再更新信息回数组中,此处本人犯过错,需谨慎!!!)

 

Main类(主入口)

 

使用(List集合)ArrayList实现-新闻管理系统

News类(封装的新闻)

 
NewsAgency类(方法集合体) (注意此处根据自动生成的有顺序的编号进行标识和索引,所以不用遍历整个集合,直接根据索引值判断即可)
 

Main类(主入口)

 

使用(Map集合)HashMap实现-用户管理系统

User类(封装的用户)

 

Main类(主方法)

 

文件类File


定义

  • Java中的File类,表示本地硬盘中的文件(文件和目录)的一个类。
  • 通过这个类创建的对象,可以操作对应的文件。

构造方法 

常用构造方法名说明File(String pathName)根据文件的完整路径创建File对象File(String parent,String child)根据文件的父目录路径和自身路径创建File对象File(File parent,String child)根据文件的父目录对应的File对象和自身路径创建File对象

常用方法

方法名说明exists()判断文件是否存在isFile()判断是否为文件isDirectory()判断是否为目录getName()获取文件名getPath()获取文件相对路径getAbsolutePath()获取文件绝对路径length()获取文件所占字节delete()删除文件或空目录mkdir()创建目录list()获取某个目录下的第一层子文件的名称的数组

IO

流Stream

特点

  • 在Java中,流用于表示计算机硬盘与内存之间传输数据的通道。
  • 将内存中的数据存入到硬盘中,称为写write,也称为输出Output。
  • 将硬盘中的数据存入到内存中,称为读read,也称为输入Input。

流的分类

字节输入流InputStream
FileInpuStream、ObjectInputStream

 字节输出流OutputStream
FileOutputStream、ObjectOutputStream

字符输入流Reader
FileReader、BufferedReader、OutputStreamWriter 

字符输出流Writer
FileWriter、BufferedWriter、InputStreamReader 

按方向分类 

  • 输入流:InputStream、Reader(将硬盘中的数据读取到内存中)
  • 输出流:OutputStream、Writer(将内存中的数据写入到硬盘中)

 按类型分

  • 字节流:InputStream、OutputStream(读写非文本类型文件。如图片、音视频、其他文件等。)
  • 字符流:Reader、Writer(读写纯文本类型文件。如txt、md等)

应用场景 

  • 如要将硬盘中某个txt文件中的内容读取到程序中,使用Reader。
  • 如要将硬盘中的某个图片读取到程序中,使用InputStream。
  • 如要将程序中的文本写入到硬盘中为txt类型文件时,使用Writer。
  • 如要将程序中的数据写入到硬盘中为非文本文件时,使用OutputStream。

流的四个父类的特点 

  • 这四个父类都是在java.io包下,都是抽象类,不能直接创建其对象,使用其子类创建对象。
  • 这四个父类中都定义了close()方法,用于关闭流对象,释放资源。
  • 输入流(InputStream和Reader)都有read()方法读取数据到内存中,输出流都有write()方法写入数据到硬盘中。
  • 输出流(OutputStream和Writer)都有flush()方法,用于将流中的数据冲刷到硬盘中
    在使用输出流对象时,一定要调用flush()或close()方法后,才能真正将数据写入到硬盘中。
  • 所有的流中,以Stream结尾,都是字节流,数据以字节传输;以Reader或Writer结尾的,都是字符流,数据以字符传输。
  • 读取硬盘中的数据,使用输入流,读取的文件必须存在;将数据写入到硬盘中,使用输出流,文件可以不存在,但父目录必须存在。
  • 读入或写入文本时,使用字符流;读取或写入非文本时,使用字节流。

使用FileInputStream和FileOutputStream实现-单文件的复制

 

文件夹的复制

 

序列化和反序列化应用

Person类(实现Serializable接口)

 

Main类

 

网络编程

InetAddress类

定义

表示IP对象的一个类。

Socket类和ServerSocket类

相同点

都属于Socket(套接字)对象,表示网络中的某个端点。

不同点
Socket指普通端。
ServerSocket指服务器端。

使用套接字对象实现两个端点(Socket和ServerSocket)之间发送文件

服务端

 

客户端

 

进程和线程

进程Process

进程就是操作系统中执行的程序。一个程序就是一个执行的进程实体。每个运行中的进程,都有属于它独立的内存空间,各个进程互不影响。

线程Thread

  • 线程是一个进程中的执行单元,一个进程中可以有多个线程。
  • 多个线程,可以访问同一个进程中的资源。
  • 每个线程都有一个独立的栈空间,这些线程所在的栈空间位于同一个进程空间中。

多线程

  • 如果一个进程中,同时在执行着多个线程,就称为多线程。
  • 多线程可以提高程序执行效率。如多个窗口卖票,可以加快卖票的效率。
  • 其实每个执行的Java程序,都是多线程执行,main方法称为主线程,还有gc线程(守护线程)在同时运行。

并行和并发 

并行

各个进程同时执行。

 并发

多个线程同时执行,称为并发。

同步和异步

同步

所有的任务排队执行。

 异步

在执行任务A的同时,执行任务B。

Java中的线程Thread类 

获取当前正在运行的线程对象

 

 创建一个线程对象(构造方法)

常用构造方法名说明Thread()创建一个默认的线程对象Thread(String name)创建一个指定名称的线程对象Thread(Runnable target)将一个Runnable对象包装为线程对象Thread(Runnable target,Stringname)将一个Runnable对象包装为线程对象同时设置线程名

常用方法

方法名作用start()让线程进入就绪状态run()线程获得执行权时执行的方法(线程要做的事情)Thread.sleep(long m)设置当前线程休眠m毫秒Thread.currentThread()获取当前执行的线程对象

实现多线程

方式一:继承Thread类

  • 创建一个类,继承Thread类。
  • 重写Thread类中的run()方法。
  • 创建自定义的线程子类对象后,调用start()方法。

方式二:实现Runnable接口(建议使用) 

自定义一个类,实现Runnable接口。
重写run()方法,将多线程要执行的内容写在该方法中。
创建Runnable接口的实现类对象。
使用构造方法Thread(Runnable target)或Thread(Runnable target,String name)将上一步创建。
的Runnable实现类对象包装为Thread对象。

方式三:使用匿名内部类 

使用匿名内部类充当Runnable接口的实现类。

生命周期 

新生状态

  • 当线程对象被创建后,就进入了新生状态。

就绪状态

  • 当某个线程对象调用了start()方法后,就进入了就绪状态。
  • 在这个状态下,线程对象不会做任何事情,只在等他CPU调度。

运行状态

  • 当某个线程对象得到CPU时间片(CPU执行这个线程的机会所给的时间),则进入运行状态,开始执行run()方法。
  • 不会等待run()方法执行完毕,只会在指定的时间内尽可能地执行run()方法。只要调用玩run()方法后,就会再进入就绪状态。

阻塞状态

  • 如果某个线程遇到了sleep()方法或wait()方法时,就会进入阻塞状态。
  • sleep()方法会在指定时间后,让线程重新就绪。
  • wait()方法只有在被调用notify()或notifyAll()方法唤醒后才能重新就绪。

终止状态

  • 当某个线程的run()方法中的所有内容都执行完,就会进入终止状态,意味着该线程的使命已经完成。

守护线程

特点

  • 如果将一个线程设置setDeamon(true),表示该线程为守护线程。
  • 守护线程会随着其他非守护线程终止而终止。

多线程访问同一个资源 

可能出现的问题

多个线程对同一对象异步进行操作,导致结果不能达到预期。

出现问题的原因

  • 由于线程调用start()方法后,就进入就绪状态。如果获得了CPU时间片,就开始调用run()方法,调用run()方法后,就会再次进入就绪状态,不会等待run()方法执行完毕,所以在线程A执行run()方法的时候,线程B也开始执行了,这样就会出现数据共享的问题。
  • 因为现在所有的线程都是异步(同时)执行。

如何解决

让线程同步(排队)执行即可。这样一来,某个线程执行run()方法的时候,让其他线程等待run()方法的内容执行完毕。

synchronized关键字

可以修饰方法或代码块

修饰方法

写在方法的返回值之前,这时该方法就称为同步方法。

 
 

修饰代码块

写在一个独立的{}前,这时该段内容称为同步代码块。

 
 

原理

  • 每个对象默认都有一把"锁",当某个线程运行到被synchronized修饰的方法时,该对象就会拥有这把锁,在拥有锁的过程中,其他线程不能同时访问该方法,只有等待其结束后,才会释放这把锁。
  • 使用synchronized修饰后的锁称为"悲观锁"。
  • 方法被synchronized修饰后,称为同步方法,就会让原本多线程变成了单线程(异步变为同步)。

死锁

场景

当多个线程同时获取不同资源时,恰好获得的资源都是对方下一步执行所需的资源,但是双方都在等待资源发放,导致多个线程一直不结束运行,也不继续执行下去。

解决方式

方式一

  • 让两个线程获取资源的顺序保持一致。

方式二

  • 让两个线程在获取资源A和B之前,再获取第三个资源,对第三个资源使用synchronized进行同步,这样某个线程在获取第三个资源后,将后续内容执行完毕,其他线程才能开始执行。

多线程相关面试题 

实现多线程的方式?

  • 继承Thread类
  • 实现Runnable接口后,包装为Thread对象
  • 匿名内部类

为什么说StringBuilder或ArrayList、HashMap是非线程安全的?

因为多个线程对这些类型创建的对象进行操作不能达到预期的结果。

个人总结

  • 上一篇: java基础helloworld
  • 下一篇: 在java基础
  • 版权声明


    相关文章:

  • java基础helloworld2025-04-22 14:50:01
  • java基础经常忘2025-04-22 14:50:01
  • java异常基础2025-04-22 14:50:01
  • java学习基础语法2025-04-22 14:50:01
  • 约瑟夫java基础2025-04-22 14:50:01
  • 在java基础2025-04-22 14:50:01
  • java语言程序设计基础篇目录2025-04-22 14:50:01
  • java基础3762025-04-22 14:50:01
  • 零基础学java 下载2025-04-22 14:50:01
  • java基础语录代码2025-04-22 14:50:01