String类概述

这个String类是被final所修饰 因此它是不能被继承的

所有的类都是默认继承于object类

 String类有两种形式

str是一个变量

注意:

person是变量  是引用类型

new Person();这个东西是在堆上 

一种是通过String类创建一个变量把这个变量赋值一个字符串

 new出来一个对象

通过引用来打印一个字符串

第三种

 两种形式是真是假

这就要看String类在内存中的布局了

 String的构造方法可以查看

 哈哈哈哈感觉好干啊!!!!!

现在是2021年11月11日凌晨0点01分

好干啊!!!!!!!!!!!!!!!!!!

18年了我天啊!!!!!!!!我怎么还单身啊!!!!!!!

算了

我还是分析String内存存储吧 害

 

1.字符串常量池

从JDK1.7开始我们就把字符串常量池放到堆中去了

因此我们在堆中开辟一块空间叫做字符串常量池

字符串常量池只存放字符串常量

它不会存放除字符串之外的常量如:final int a;之类的

2.

之后由于hello是由双引号引起来的

所有hello是一个字符串常量  它存放于字符串常量池中

它是会占用内存的  

因此str1指向这一块内存地址

3.

当str2再一次new一个对象之后

我们由于在字符串常量池中已经存了一个hello了

因此我们不把hello再一次存到字符串常量池中  只是会指向同一个hello

由于str2 new了一个对象

因此肯定在堆上开辟了一块空间

original表示是一个引用地址  表示str2创建出的hello的地址

又由于hello已经由str1创建过了

那么original的地址就是第一个hello处的地址

查阅可知:

我们构造方法中引用的普通的成员变量就是value

并且它的类型是一个数组

通过查阅可知 value是一个数组

这一块新空间肯定会有一个新地址 

str2指向new String地址设为888

 ok

其实我们总结一句话就是

一个hello在字符串常量池中我们只可以存储一份

由于str3并没有像str2一样new一个对象

因此我们在再一次String str3="hello";时就表示指向字符串常量池中同一位置的hello

 总结:

1.一个相同的字符串常量只能在字符串常量池中开辟一次空间

如果往后还有相同的开辟时  我们都默认指向同一位置

2.我们在比较str1  str2 str3时都是比较它们的地址的

3.当你new一个对象之后中间地址会改变

再来一个

慢慢来

由于在编译的过程中常量字符串已经拼接完成了

因此我们可以知道

str1和str2是指向同一个堆上的字符串常量池上的hello的

ok 没问题的这个 

因此str1==str2

 接下来我们来看str3

这个str3的过程·:

一开始我们new了一个对象这个对象初始参数我们是定义为hel的

由于hel是不等于hello的因此我们在字符串常量池另外开辟一块空间来存hel

并且new的对象指向它

后来我们又加上了lo

中间这个+号起作用

它俩在堆上的空间进行拼接成hello

最终这个new出来的对象是指向这个拼接出来的hello’的

易知str1不等于str3 

 

 是否改变值?

切记不要以为传引用就可以改变值了  呵呵

str1="abc";只是代表它改变指向

指向了这个在堆上重新开辟的字符串abc

 例子

 分析一下:

先执行main

那么str1是局部变量存到栈上开辟空间

并且它是在堆上的字符串常量池开辟空间存放常量字符串hello的

因此str1执行地址设为888的hello

之后我们创建一个数组

这个数组在堆上开辟一块空间   存放'a'的

数组名val指向它

之后我们调用方法func  

分析 :参数的传递过程

str1是实参传给形参 

由于你传的是str1  str1原来指向地址为888的hello

因此str一开始也存放这个地址并且指向堆上字符串常量池上的hello

形参str在栈空间上开辟一块空间指向hello这个常量字符串

之后由于把这个str这个引用赋值为abcdef

因此指向改变  变为指向abcdef

但是hello并没有被改变

但是另外一个实参val传过去之后 传给数组array

形参数组名在栈上开辟空间 指向在堆上开辟的数组空间

array[0]='g';

这里是之间通过数组元素改变的

因此值改变

注意:

比较两个字符串的内容我们常用

str1.equals(str2)

 

一般我们比较两个字符串就是比较它俩的引用指向是否相同

注意2:

如果是一个简单类型  我们可以直接用"=="进行判断

然而当是一个字符串类型时  我们就不可以用==进行比较了

因为我们一般比较的是两个字符串的指向  

因此我们常用 str1.equals(str2) 来比较两个字符串是否相等

记住一点:

equals前面的那一个字符串不可以是null

否则会发生空指针异常 

但是后面的那个可以用null 

intern方法:

str1先在字符串常量池中开辟一块空间存hello

然后是str2  先在堆上开辟一块空间存

在调用intern方法的时候我们先看在字符串常量池中是否与我们str2中要开辟的字符串hello同名的常量字符串  

如果有

那么就返回常量池中这个hello的引用  即是赋值这个地址给str2

 那么当使用intern方法的时候

我们并没有提前在常量池中有一个相同的hello

如图 str1在str2后面

 分析:

如果没有intern方法 那么我们可以知道

先在字符串常量池中开辟一块空间存hello

在堆上new出来一块新空间之后  str2是要指向new String那一块空间的

这块空间是指向常量池中的hello的

但是这里有intern方法

这个就会导致  常量池中的hello地址被返回到str2中

即是str2被赋值了888这个地址

那么str2指向hello

之后我们又开辟了str1

同样指向第一个hello  

因此结果为true

intern()方法又称手动入池 

记住最好不要写下面这种代码:

因为它不可能在常量池中给你拼接

它只会生成许多临时的变量

因此不建议这种写法

字符串是不可以变化的  每一次都会生成一个新的对象

 最终结果虽然可以

但是中间生成大量的临时变量

 修改字符串:

 表示从第一个位置即是从e开始提取出来

然后再拼接一个h

最后得到了字符串hello 

反射可以直接改变Hello变成hello

 拼接成字符串

 情况1:

通过调用String的构造方法  来拼接字符串

情况2:

把val的字符数组在偏移量为1的情况下拼接三个字符

情况3:

提取处下标为1的字符  即是e

情况4:

把字符转换为字符数组

 理解就行  没必要记住

利用

char ch=str2.charAt(i);提取i下标处的字符

看是否为一个只有数字的字符串?

 

何时用byte[ ]还是char[ ]?

equalsIgnoreCase忽略大小写的区别来比较两个两个字符串

 比较两个字符串的长度

 利用str1.compareTo(str2)来进行比较

由于前面的abc都相等的  后面str2多了def

返回-3  

由于str1是小于str2的  小几个?小三个长度

因此返回-3

str1.compareTo(str2)

结果返回4

为什么?因为首字符e大于a  大4个ASCII码值

 当这种e小于f时

str1.compareTo(str2) 返回-1

因为从第一个开始比较e比f小1

因此后面的就不会再去比较  直接返回-1

 规则:

 字符串截取:

在Java当中我们截取的时候默认是左闭右开的

 因此这里(1,4)即是等价于[1,4)

那么从b开始截取到第二个b 

注意截取的是三个而不是四个

 1.trim

通过查找可知trim的返回值是String

因此要用String类来接收它

 字符串查找

1.查找是否包含字串

2.

从头开始找abc如果找到了 那么就返回找到那个字符串abc的第一个字符的下标

即是2 

 3.从指定位置开始找

 从下标为3的位置开始找

4.从后往前找

 5.从指定位置开始 从后往前找

fromIndex表示从指定的位置去查找

 研究以下两种算法:

6.

7.

 

 表示从偏移量1处开始

举个例子:

第一个a的偏移量为0 

第一个b的偏移量为1  

字符串是否是以指定的字符串abc开头的

 8.

 判断是否由指定字符串结尾

看是否是以指定字符串bcde结尾   

若是      返回true  

若不是  返回false

 注意:

重点来了

 

split类的返回值是一个String数组 类型

把这个字符串进行拆分

拆分的条件就是以空格为拆分条件 

 

先分析一下这个foreach语句

它起到的作用是遍历这个数组

冒号的左边是这个数组的类型

右边是数组的数组名 

 

 limit表示限制了所分的组数

只分为两组

分割IP地址 

对于这些符号处理时 我们都要加上"\\" 

原因如下:

在想让机器知道你是什么符号的时候

必须要加上一个转义字符  \

但是呢?

这与c语言不一样  

我们必须用两个'\'来表示这就是转义字符'\'

如果用一个'\'我们Java当中就不知道你这是转义字符'\'

因此我们用 \\  来表示一个转义字符  \

因此我们得用"\\."来表示一个 .

 

 但是\\时就有点恶心了

插一条转义字符的题:

"\0leo"

答案是0 而不是3

因为C语言中求字符串长度是遇见\0就停止

即\0是字符串的结束标志 

并且记住一点在C语言算字符串长度时\0不算到长度中

如:"ABCD"的字符串长度为4

因为字符串是默认省略书写了\0  自带但不显示  

这里其实就是"ABCD\0" 故结果为4

" abc\n\\\'\" " 

长度为7   分析如下:

a   b     c   \n      \\     \'     \''   

后面四个都是转义字符  最后两个为  单引号和双引号

“abc\\\061xy”

长度为7

a b c  \\   \061   x   y

“abc\\\0xy”

长度为4

a    b   c   \\   

\0表示结束且不算里面   

\\为转义字符  即是\

 想以-和#同时分割

用 " |-|#"

但是注意第一个|之前要加上一个空格 不然就错了

这个了解就行  不常用

注意: 

进行多次分割

 先以&分割

再以=分割

 笔试oj

import java.util.Scanner;//导包
public class Main {
    public static String func(String str){
        //把输入的字符串以空格为分割标识
        String[] strings=str.split(" ");
        String ret="";
        //左边表示类型  s为定义的变量
        //右边的表示数组名
       for(String i:strings){
            //数组被以空格拆开之后
            //我们再进行拼接即可
            ret+=i;
        }
        return ret;
    }
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        //这里while表示多组输入
        while (scan.hasNext()) {
            //切记不可以用scan.next因为我们输入的字符串中间有空格
            //用next遇见空格就直接结束了
            String str = scan.nextLine();
            String ret = func(str);
            System.out.println(ret);
        }
    }
}

 当while多组输入时

如何停止?ctrl+D

1.

toUpperCase与tolowerCase

都只是对字母有效

 2.

这里的length() 表示方法

 但是arr.length这里的length表示arr的属性

 3.

 4.

逆序一个字符串abcdef

public class Main {
    public static String reserve(String str,int begin,int end){
        //意思是把字符串中的每一个字符 放到数组中去
        char[] arr=str.toCharArray();
        while(begin<end){
            char temp=arr[begin];
            arr[begin]=arr[end];
            arr[end]=temp;
            begin++;
            end--;
        }
        //不可以直接传回这个数组  因为返回类型是String
        //因此我们要new一个String类型的
        return new String(arr);
        //返回这个的方法二
        //return String.copyValueOf(arr);
    }

    public static void main(String[] args) {
        String str="abcdef";
        int begin=0;
        int end=str.length()-1;
        String ret=reserve(str,begin,end);
        System.out.println(ret);
    }
}

5.

算无良策  唯手熟尔

题中要把前面size个移到后面去

size是自己输入的  

例如 size==3那么把前三个字符移到后面

如abcd  就变成  dabc

  

算法思想:

第一步:先把 前面要移动的size个字符逆序

第二步:再把size个字符 后面的字符进行逆序

第三步:再把整体逆序一遍

import java.util.Scanner;
public class Main {
    public static String reserve(String str,int begin,int end){
        //意思是把字符串中的每一个字符 放到数组中去
        char[] arr=str.toCharArray();
        while(begin<end){
            char temp=arr[begin];
            arr[begin]=arr[end];
            arr[end]=temp;
            begin++;
            end--;
        }
        //不可以直接传回这个数组  因为返回类型是String
        //因此我们要new一个String类型的
        return new String(arr);
        //返回这个的方法二
        //return String.copyValueOf(arr);
    }
public static String func(String str,int size){
        //判断传入的size是否可取
        if(str==null||size<0||size>str.length()){
            return null;
        }
     str=reserve(str,0,size-1);
     str=reserve(str,size,str.length()-1);
         str=reserve(str,0,str.length()-1);
        return new String(str);
}
    public static void main(String[] args) {
        Scanner scan=new Scanner(System.in);
        while(scan.hasNext()){
            String str=scan.nextLine();
            int size=scan.nextInt();
            String strings=func(str,size);
            System.out.println(strings);
        }
    }
}

3.后两者有许多String不具备的方法

为什么StringBuilder  StringBuffer不会产生大量的临时对象呢?

因为它是调用append  append的返回值类型是this

最后进行一次toString()的原因就是为了把这个拼接之后的字符串赋值给ret

 1.

通过反汇编我们可以知道

每一次循环都会new出来一个新对象  那么就会导致运行之后产生大量的对象

2. 

 

 总结:

1、重写实现的是运行时的多态,而重载实现的是编译时的多态。

2、重写的方法参数列表必须相同;而重载的方法参数列表必须不同。

3、重写的方法的返回值类型只能是父类类型或者父类类型的子类,而重载的方法对返回值类型没有要求。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值