一、API(我在开发中几乎不用这个东西,大部分时间面向百度和同事,哈哈)
在学习面向对象编程思想,遇到需求时,先去找有没有解决问题的功能(函数)存在。这些解决问题的功能(函数)通常是封装在类中(功能类),使用这些功能类基本可以解决开发中大部分的问题。
问题:这些解决问题的功能类都在哪里?
在java设计时,已经提供了很多解决问题的封装类。这些解决问题的封装类我们统称为:API。在开发中,只要去相应的包(文件夹)中去找对应的封装类就可以解决问题。
API:application programming interface。应用程序接口。我们这里通常把api简称为帮助文档。
想要使用java提供的解决各种问题的API,就需要先学会如何查阅API文档。
二、API的查找
下图操作,点击选项,选择显示标签
在输入框中输入英文进行查找
三、String类
学习常量的时候(第二天)介绍过Java中的所有常量:
整数、小数、字符、字符串、null、真假值true false;
字符串常量,它在Java中不属于基本数据类型, 而是引用类型,也称为类类型。Java中使用String这个类描述字符串这种常量数据。
API中对java.lang.String类的描述:
String描述的字符串,所有在Java程序中使用双引号引用起来的数据都是一个对象。
String类中描述的是所有字符串常量,一旦书写完成,它就是一个固定值,这个数据不能改变。
注意:字符串常量,它属于对象,但是它不是存储在堆空间中,而是存储在方法区中的字符串常量池中。字符串常量池中保存的就是所有的字符串数据。只要我们书写了双引号,不管双引号中间是什么数据,这些数据都会立刻在字符串常量池中保存。并且一直存在,不会被改变。
System.out.println(s1==s2);//这里比较的是内存地址名是否相等
String类中的api告诉我们字符串是常量不能被改变,这里的意思是在常量池中的字符串中的数据值不能被改变。而指向这些字符串的引用变量空间中的内存地址值是可以改变的,这样可以让同一个String类型的引用变量空间指向方法区中不同字符串对象空间所保存的常量数据。
四、String构造函数
后期查阅api,看到一个类提供的构造函数,那么我们就可以知道这个类肯定给我们提供的不同构造函数都可以创建出这个类的一个对象。
注意:使用双引号本身就可以得到一个字符串对象。
String类提供了大量的构造函数,目的是可以帮助我们将其他的数据变成字符串对象。
只要使用String类的构造函数创建的对象,那么这个对象就会在堆中出现。
而在创建出的字符串对象中的字符数据保存在常量池中。
1.字节数组中的数据变成字符串
一下代码有三个对象
注意:在堆中开辟的字符串空间中有一个引用保存着字符串常量池的字符串的内存地址名。
2.字符数组或int类型的数组转成字符串
代码如下所示://String(char[] value):把字符数组的数据封装成字符串对象
char[] chs = {'h','e','l','l','o'};
String s2 = new String(chs);
System.out.println("s2:"+s2);
System.out.println("---------");
3.字符串或者字符串缓冲区中的数据变成字符串
面试题:问以下两行代码分别有几个对象?
String s = new String(“abc”);2个 String s = “abc”;1个
五、String类的判断方法
1.boolean equals(Object obj):比较字符串的内容是否相同。
2.boolean equalsIgnoreCase(String str):比较字符串的内容是否相同,忽略大小写。
3.boolean startsWith(String str):判断字符串对象是否以指定的str开头。
4.boolean endsWith(String str):判断字符串对象是否以指定的str结尾。
Object:是类层次结构中的根类,所有的类都直接或者间接的继承自该类,如果一个方法的形式参数是Object,那么这里我们就可以传递它的任意的子类对象。
注意:比较两个字符串相等,我们不应该使用==(恒等符号),因为==是用来比较具体常量数值的。
而由于字符串是对象,所以我们应该使用String类中的equals函数对两个字符串进行比较,因为equals函数是用来比较两个对象是否相等。(==比较的是内存地址名)
六、String类的操作方法
int length():获取字符串的长度,其实也就是字符个数
char charAt(int index):获取指定索引处的字符
int indexOf(String str):获取str在字符串对象中第一次出现的索引
String substring(int start):从start索引开始截取字符串,截取到字符串最后
String substring(int start,int end):从start开始,到end结束截取字符串【start,end)。
String s="abcaef";----->s.length();s.charAt(1);s.indexOf(a);s.substring(2);s.substring(0.6)。
七、String的转换方法
char[] toCharArray():把字符串转换为字符数组;char[] chs = s.toCharArray();
String toLowerCase():把字符串中的所有大写字母转换为小写字母
String toUpperCase():把字符串中的小写字母转换为大写字母
String arrayToString(arr):把数组转为字符串
String trim():trim()函数是去除字符串两端的空格,而不是字符串中所有的空格。
String[] split(String str):按照指定的字符串分割字符串,例如逗号,切分。注意:切割的时候指定的字符串最好一定是长串中存在的内容;如果指定的字符串不在长串中,那么程序就会把整个字符串作为返回值,那么接收切割后的字符串数组中只存储一个数据,即原来的长串。
八、字符串缓冲区
在String的api中我们知道String类是不能更改的,需要更改应该找字符串缓冲区。Java中提供两个字符串缓冲区:Stringbuffer和Stringbuilder。
缓冲区就是一个容器是临时的空间,它里面可以临时存储数据。
字符串缓冲区的本身就是一个容器,只不过这个缓冲区最后会把里面所有的数据转换为字符串而已。
当我们需要对字符串进行数据的修改,这时不能直接使用String类,而把需要修改的字符串先存储到字符串缓冲区容器中,在容器中进行各种修改,等最后确定不再修改的时候,把里面的数据变成一个字符串,然后存储在字符串常量池中。
JDK的在线文档可以参考-------->(在线文档-jdk-zh)
①.StringBuilder 概述
String和StringBuilder的区别: String的内容是固定的,StringBuilder的内容是可变的。
一个可变的字符序列。此类提供一个与 StringBuffer
兼容的 API,但不保证同步。该类被设计用作 StringBuffer
的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer
要快。原因是它不执行同步,所以速度更快。
- 是一个字符串缓冲区,其实就是一个容器。
- 长度是可变的,任意类型都可以。注意:是将任意数据都转成字符串进行存储。
- 容器对象提供很多对容器中的数据操作的功能,比如添加,删除,修改,查询。
- 所有的数据最终都会变成一个字符串。
字符串缓存区和数组最大的不同就是数组存储完可以单独操作每一个元素,每一个元素都是独立的。字符串缓存区,所存储的元素都会被转成字符串,而且变成了一个更长的字符串。
StringBuilder类的常用方法
A构造方法
- 对于StringBuilder()构造函数,其初始容量为16个字符表示,如果存在StringBuilder的数据超过了16个字符,这个容器可以自动扩容(容器空间自动变大)。(经常使用)
解释:StringBuilder底层体现就是一个字符数组,StringBuilder类的对象将数组封装起来,然后对外提供很多便捷方法,而数组本身是没有什么太多方法的。如果外界将数据存放到底层的数组中,如果底层数组空间存放不下外界传递过来的值,那么jvm会基于原来存在的数组在创建一个新的数组,长度是原来数组的一倍+2,然后jvm将原来数组的数据全部复制(遍历数组,将数据添加到新的数组中)到新的数组中,然后在数组后面的空间中给数组添加新的值,如果还是存不下在创建一个新的数组。
2.对于StringBuilder(int capacity)构造函数来说,capacity表示容器的容量,如果在开发中想自己设置缓冲区大小,可以通过此构造函数来实现;
3.任何容器:它都围绕容器中的数据的 增 删 改 查 而设计的方法。
B:成员方法:
public int capacity():返回当前容量 (理论值)
public int length():返回长度(已经存储的字符个数)
public StringBuilder append(任意类型):添加数据,并返回自身对象
public StringBuilder reverse():反转功能
②.StringBuffer概述
线程安全的可变字符序列。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
tringBuffer
上的主要操作是 append
和 insert
方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append
方法始终将这些字符添加到缓冲区的末端;而 insert
方法则在指定的点添加字符。
例如,如果 z
引用一个当前内容为 "start
" 的字符串缓冲区对象,则此方法调用 z.append("le")
会使字符串缓冲区包含 "startle
",而 z.insert(4, "le")
将更改字符串缓冲区,使之包含 "starlet
"。
通常,如果 sb 引用 StringBuilder
的一个实例,则 sb.append(x)
和 sb.insert(sb.length(), x)
具有相同的效果。
当发生与源序列有关的操作(如源序列中的追加或插入操作)时,该类只在执行此操作的字符串缓冲区上而不是在源上实现同步。
每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即 StringBuilder。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。
以上是StringBuffer概述,没有更好的方法,只有最合适的方法,所以请根据场景进行使用。
----------------------------------------------------------------------------------------------------------------------------
1.线程安全和线程不安全的区别?
线程安全和线程不安全都是指多线程情况下,线程安全是指一个进程启动,主线程执行时调用开启了两个以上的子线程,去同时执行一段代码,这段代码中的全局变量,有被写的情况,那么就考虑到同步数据的同步问题(一般是方法上用关键字synchronized修饰 ,或者创建Lock对象,枷锁,解锁,此处不做深入展开),能保证数据同步的方法就是线程安全的,不能保证数据同步的方法就是线程不安全的。
2.线程同步是什么意思或多线程的同步是什么意思?
线程同步是多个线程同时执行一段代码,对代码中的全局变量或者可能需要保存进入数据的的数据进行操作,先执行的线程的修改还未提交时,可能会影响后面执行线程的结果产生错误影响,就需要进行数据的原子性的同步。
3.java中实现多线程的方式?
一种是继承Thread类,另外一种是实现Runable接口。(准确来讲应该有三种,还有一种是实现Callable接口,并与Future、线程池结合使用,有兴趣看这里Java并发编程与技术内幕:Callable、Future、FutureTask、CompletionService_Evankaka的专栏-CSDN博客)