java截取固定大小图片_跟光磊学Java开发-字符串的应用和内存分析

浅谈API的学习方法

在后续的学习过程中,还会大量使用JDK或者第三方组件、框架提供的API,而在学习这些API时可以利用面向对象的思想去使用它们。

62800364529a161f3d72b3a035599b21.png
  1. 了解它的体系结构,即它继承了哪个父类,在Java领域默认都是直接间接继承java.lang.Object,如果父类是一个抽象类,需要抽象类的方法,还有就是实现了哪个接口,接口中的方法都应该被实现类实现。
  2. 了解它的成员变量,了解底层实现。
  3. 了解它的构造方法,构造方法用于创建该类的对象,如果它的构造器是私有的,那么它通常是一个工具类,提供的方法都是静态方法,直接通过类名.方法名调用即可。
  4. 了解它的普通方法,主要是关注方法如何调用,关于方法主要是方法的重载、重写、参数和返回值,声明的异常。
  5. 多看源码,主要是方法的实现,多调试流程,多仿写,多改写

String类

String类概述

java.lang.String类表示字符串,字符串是日常开发中最常用的数据类型。

531e23b0127fe54a1b80cf18d40ace40.png


因为Java主要是做服务端,也就是后端。当前端发起HTTP请求传给后端的数据格式是字符串,也就是String类。
在Java程序中所有使用一对双引号("")包含的内容(例如“helloworld”)都是String对象的实例。

String类特性

String类是基于字节数组实现的,当操作字符串时底层是一个字节数组,而且该数组是final,也就是必须只能赋一次值,因此说String类是不可变的,每操作一次都会产生一个新的字节数组

5a9af718a3fbb2cef41bf12d30a0e6e0.png
/**   * String的特点:不可变   */  @Test  public void testStringFeatureImmutable(){    String str1="abc";    str1+="d";    //此时内存中有三个字符串对象,分别是abc,d,abcd,字符串的任何操作都会产生一个新的String对象  }

而同一个字符串常量是可以被共享的,即同一个字符串在JVM中只会有一个字符串对象。

    /**   * 两个相同的字符串在JVM中只会存储一个字符串对象   */  @Test  public void testStringFeatureShare(){    String str1="abc";    String str2="abc";  }

创建 String对象的几种方式

在使用String之前,需要借助String类的构造器创建该类的对象。
日常开发中可以通过字符串常量,字节数组和字符数组三种方式来创建String类的对象,也可以直接使用字符串常量赋值给String类型的变量创建一个String类型的对象。

/**     * String对象的几种创建方式     */    @Test    public void testStringConstruct(){        // 方式1        //直接将字面量的值赋值也是字符串对象        String str="hello";        System.out.println("str = "+str);        /*3种构造方式*/        //方式2        //空字符串        String emptyString=new String("");        System.out.println("emptyString = "+emptyString);        //方式3        //将字节数组转换为字符串        //打印的是ABCDEF        byte[] bytes=new byte[]{65,66,67,68,69,70};        String byteArray=new String(bytes);        System.out.println("byteArray = "+byteArray);        //打印结果是cde        String byteArrayBetweenAnd=new String(bytes,2,3);        System.out.println("byteArrayBetweenAnd = "+byteArrayBetweenAnd);        //方式4        //将字符数组转换为字符串        char[]chars=new char[]{'a','b','c'};        String charArray=new String(chars);        System.out.println("charArray = "+charArray);    }

程序运行结果

d651e727211c42bc13088fa828911a5b.png

使用new关键字创建的字符串对象,每次都会在堆内存中开辟内存空间,虽然字符串内容相同,但是地址值不同。
但是当将一个字符串常量赋值给一个字符串变量时,此时的字符串常量存储在常量池当中,相同的字符串常量JVM只会存储一份,也就是同一个String对象。

   /** 字符串对象存储的差异 */  @Test  public void testStringInstanceDiff() {    char[] chars = {'a', 'b', 'c'};    String str1 = new String(chars);    String str2 = new String(chars);    // ==比较的是内存地址,因为每次new都会在堆内存申请新的空间 因此地址值是不相等    System.out.println("str1 == str2 " + (str1 == str2));    // 此时abc位于常量池中,相同的常量值JVM只会存储一份    String str3="abc";    String str4="abc";    //此时两个引用变量是相等的,因为str3和str4的变量值都位于常量区,它俩都指向同一个常量区地址    System.out.println("str3 == str4 " + (str3 == str4));  }

字符串存储内存结构

4e35519df082d4ab5f87499934c5b451.png

程序运行结果

91818bba0cfdcfa5c959a06b2732dc9c.png

String对象常用方法的使用

  1. 字符串比较的方法
    字符串比较是日常开发中常用的方法,String对象提供了两个方法用于字符串对象的比较:equal()方法和equalsIgnoreCase()方法
  • equals()方法用于比较两个字符串对象是否相等,不忽略大小写。
  • equalsIgnoreCase()方法用于比较两个字符串对象是否相等,忽略大小写。
    在开发中不要使用==判断引用数据类型是否相等,因为默认比较的是引用变量的地址值。
  /**   * 字符串相等性比较   * == 操作基本数据类型比较的是变量值是否相同   * == 操作引用数据类型比较的是地址值是否相等   * equals()方法用于比较两个字符串相等,不忽略大小写   * equalsIgnoreCase()方法用于比较两个字符串是否相等,忽略大小写   *   */  @Test  public void testStringEquals(){    int source=10;    int target=10;    System.out.println("source == target ="+(source==target));    String str1="abc";    char[] chars={'a','b','c'};    String str2=new String(chars);    // 因此不能使用==判断两个字符串对象的内容是否相等    System.out.println("str1 == str2 ="+(str1 == str2));    // 比较两个字符串对象的内容相同使用equals()方法,返回一个布尔值,区分大小写    System.out.println("str1.equals(str2) = "+str1.equals(str2));    //例如abc和ABC会返回false    String str3="ABC";    System.out.println("str1.equals(str3) = "+(str1.equals(str3)));    //某些应用场景会忽略大小写,例如验证码,此时可以使用equalsIgnoreCase()方法    System.out.println("str1.equalsIgnoreCase(str3) = "+(str1.equalsIgnoreCase(str3)));  }

程序运行结果

fa0efa2c02e895587cc9839822ed86e1.png
  1. 获取字符串
  • length()方法用于获取字符串的长度,其本质就是除了0以外的字符个数
  • concat()方法用于字符串的拼接,等价于+
  • charAt(int index) 方法用于查找指定索引的字符,结合for循环可以实现字符串的遍历
  • indexOf(String str)查找指定字符串第一次出现的索引位置,还有个重载的方法indexOf(String str,int index),可以实现获取指定第n个次出现的字符串
  • lastIndexOf(String str) 反向查找指定的字符串出现的索引位置
  • subString(int beginIndex) 按照指定的开始索引截取字符串
  • subString(int beginIndex,int endIndex) 按照指定的开始索引和结束索引截取字符串,截取的字符串不包含结束索引的字符串
 /**   * 获取字字符串   */  @Test  public void testStringGet(){    String str="HelloWorld";    //获取字符串的长度    int length =str.length();    System.out.println("HelloWorld字符串的长度是 "+length);    //等价于 HelloWorld+你好,世界    String concatStr = str.concat("你好,世界");    System.out.println("拼接后字符串内容是"+concatStr);    System.out.println("拼接之前的字符串内容是"+str);    //获取2索引位置的元素    char charValue=str.charAt(2);    System.out.println("HelloWorld字符串第二个索引的元素是"+charValue);    //结合for循环,length()方法和charAt()方法实现字符串的遍历    for (int i = 0; i < str.length(); i++) {      System.out.print(str.charAt(i)+",");    }    System.out.println();    int firstLIndex=str.indexOf("l");    System.out.println("HelloWorld字符串的第一个l字符的索引是"+firstLIndex);    //获取HelloWorld字符串的第二个字符串    int secondLIndex=str.indexOf("l",firstLIndex+1);    System.out.println("HelloWorld字符串的第二个l字符的索引是"+secondLIndex);    //获取HelloWorld字符串倒数第一个字符串l    int lastFirstLIndex=str.lastIndexOf("l");    System.out.println("HelloWorld字符串的倒数第一个l字符的索引是"+lastFirstLIndex);    //截取HelloWorld的World    String hello=str.substring(5);    System.out.println("HelloWorld截取Hello的结果是"+hello);    //截取HelloWorld的Hello    String subString=str.substring(0,5);    System.out.println("HelloWorld截取Hello的结果是"+subString);  }

程序运行结果

c052736e2de4e9b5b9c55b5e8e09da5d.png
  1. 字符串的非空判断

字符串非空判断是经常使用到的,在判断之前需要先判断对象是不是null,然后再使用isEmpty()方法判断对象的内容是不是空

 /**   * 字符串的非空判断   */  @Test  public void testStringEmpty(){    //空,没有在堆内存分配内存空间,str1不能使用,如果使用会引发空指针    String str1=null;    // 此处会抛空指针    // boolean str1IsEmpty=str1.isEmpty();    //空字符串对象,已经在堆内存分配内存空间,只是空间没有内容,没有内容,即byte[]没有元素    String str2="";    boolean str2IsEmpty=str2.isEmpty();    System.out.println("str2IsEmpty = " +str2IsEmpty);    //包含一个空格的字符串    String str3=" ";    boolean str3IsEmpty=str3.isEmpty();    System.out.println("str3IsEmpty = " +str3IsEmpty);  }

程序运行结果

d388456c53335ff9464e9dc9d4057f54.png
  1. 判断字符串是否包含指定的字符串和字符串的替换
 /**   * contains() 字符串是否包含字串   * replace()字符串替换   */  @Test  public void testStringContainsReplace(){    String parent="跟光磊学Java";    boolean isContains=parent.contains("Java");    System.out.println("字符串跟光磊学Java是否包含Java?"+isContains);    if(isContains){      //将Java替换成前端      parent=parent.replace("Java","前端");    }    System.out.println("将Java替换成前端后 parent = "+parent);  }

程序运行结果

e9cf145a71046917c99f367035c47437.png


5. 字符串大小写转换

  /**   * 字符串大小写转换   * toLowerCase() 字符串转换为小写   * toLowerCase() 字符串转换为大写   */  @Test  public void testStringUpperLower(){    String upper="ABC";    System.out.println("ABC转换为小写的结果是"+upper.toLowerCase());    String lower="abc";    System.out.println("abc转换为大写的结果是"+lower.toUpperCase());  }

程序运行结果

0332b12a385c9cf2d3814dcde2947d7d.png
  1. 字符串和字符数组、字节数组的转换
    字符串转换为字节数组时会将字符替换成对应的ASCII值
/**   * toCharyArray()字符串转换为字符数组   * 字符串转换为字节数组   */  @Test  public void testStringToCharArrayByteArray(){    String str="HelloWorld";    char[] chars = str.toCharArray();    System.out.println("HelloWorld转换为字符数组的结果是" + Arrays.toString(chars));    byte[] bytes = str.getBytes();    System.out.println("HelloWorld转换为字节数组的结果是" + Arrays.toString(bytes));  }

程序运行结果

5c3ab684342d1dd6e087d685d4baa7d8.png
  1. 字符串删除首尾空格
 /**   * trim()字符串去掉首位空格   *   */  @Test  public void testStringTrim() {    String str=" Hello World ";    System.out.println("去掉空格前是"+str);    System.out.println("掉空格后的结果是"+str.trim());  }

程序运行结果

e379060d7047256f69fb292c34e9fe0f.png
  1. 字符串按照指定的规则拆分
 /**   * split(String regex)按照指定的规则拆分字符串   */  @Test  public void testStringSplit(){    String language="C,Java,JavaScript,Go,Python,C++";    //按照逗号拆分字符串    String[]languages=language.split(",");    System.out.println("必须掌握的编程语言:"+Arrays.toString(languages));  }

程序运行结果

15218a268445d41e8140255281c51c01.png

字符串常见应用

  1. 使用字符串实现模拟用户登录
package net.ittimeline.java.core.jdk.api.lang;import java.util.Scanner;/** * 字符串应用:模拟用户登录 * * @author tony 18601767221@163.com * @version 2020/12/17 17:45 * @since JDK11 */public class StringLoginTest {  public static void main(String[] args) {    int count = 0;    String targetUserName = "tony";    String targetPassword = "123456";    int maxLoginCount=3;    Scanner input = new Scanner(System.in);    while (count < 3) {      System.out.println("请输入你的用户名");      String userName = input.nextLine();      System.out.println("请输入你的密码");      String password = input.nextLine();      if (targetUserName.equals(userName) && targetPassword.equals(password)) {        System.out.println("登录京东成功");        break;      }else{        System.out.println("用户名或者密码错误,登录失败");      }      count++;      System.out.printf("你还剩下%d次机会",maxLoginCount-count);    }    input.close();  }}

程序运行结果

f824c758637f4d858fad8501d8130590.png
  1. 字符串遍历
package net.ittimeline.java.core.jdk.api.lang;import java.util.Scanner;/** * 字符串应用:遍历字符串 * * @author tony 18601767221@163.com * @version 2020/12/17 18:02 * @since JDK11 */public class StringTraversalTest {  public static void main(String[] args) {    Scanner input = new Scanner(System.in);    System.out.println("请输入你的名字");    String userName=input.nextLine();    for (int i = 0; i 

程序运行结果

75ad81698279ddc802b1391933166121.png
  1. 统计字符串
package net.ittimeline.java.core.jdk.api.lang;import java.util.Scanner;/** * 字符串应用:字符串统计,读取用户输入的字符串,判断输入的大写字母、小字母以及数字的个数 * * @author tony 18601767221@163.com * @version 2020/12/17 18:06 * @since JDK11 */public class StringStatisticTest {  public static void main(String[] args) {      int lowerCaseCount=0;      int upperCaseCount=0;      int numberCount=0;      System.out.println("请输入一段字符串");      Scanner input=new Scanner(System.in);      String str=input.nextLine();    for (int i = 0; i < str.length(); i++){      char ch=str.charAt(i);      if(ch>=97 && ch <=97+26){          lowerCaseCount++;      }else if(ch>=65&&ch<=65+26){          upperCaseCount++;      }else if(ch>=48&&ch<=48+9){          numberCount++;      }    }    System.out.printf("你输入的字符串是%s,其中大写字母的个数是%d,小写字母的个数是%d,数字的个数是%d",str,upperCaseCount,lowerCaseCount,numberCount);  }}

程序运行结果

a85ae476669e7ed24d0dd212465d551b.png
  1. 实现Arrays.toString()方法
/** 实现Arrays.toString(int[]a)方法 */  @Test  public void testStringConcat() {    int[] numbers = {1, 2, 4, 5, 7, 8, 9, 6, 3};    //初始化拼接字符串    String str = new String("[");    //遍历数字    for (int i = 0; i < numbers.length; i++) {      if (i < numbers.length - 1) {        //不是最后数字就拼接数字和逗号        str = str.concat(numbers[i] + ",");      } else if (i < numbers.length) {        //是最后数字就拼接数字和]        str = str.concat(numbers[i] + "]");      }    }    System.out.println(str);  }

程序运行结果

c8533cb3686595c90c626aecc5ffa85e.png
  1. 字符串反转
  /** 字符串反转 */  @Test  public void testStringInversion() {    String str = "跟光磊学Java开发";    System.out.println("跟光磊学Java开发反转之前 str = " + str);    String result = new String();    for (int i = str.length()-1; i >= 0; i--) {      result+=str.charAt(i);      //    }    System.out.println("跟光磊学Java开发反转之后 result = " + result);  }
a8d1f12218c8811a173fff0e9fd81c86.png

字符串反转

StringBuilder类

StringBuilder类概述

由于String的不可变特性,每次操作都会产生一个新的String对象,这样耗时号内存。因此SUN公司又设计了StringBuilder类

9db9637e19d0c8d4ef8790578a54fd72.png


java.lang.StringBuilder表示 一个可变的字符串类,这里的可变表示StringBuilder对象中的内容是可变的。
通过其父类java.lang.AbstractStringBuilder的源码可以看出它的底层实现采用一个不是final修饰的字节数组。

6bb4902815ffa749f5c9f44a9f1ba40d.png

StringBuilder类的构造方法

在使用StringBuilder对象提供的方法之前,同样需要创建StringBuilder的对象。
我们可以使用两种方法来创建StringBuilder对象:空字符串创建StringBuilder对象和非空字符串创建StringBuilder()对象

/** StringBuilder常用构造器 */  @Test  public void testStringBuilderConstruct() {    // 使用空字符串创建一个StringBuilder对象    StringBuilder emptyString = new StringBuilder();    System.out.println("emptyString.length() = " + emptyString.length());    // 使用字符串创建一个StringBuilder对象    String str = "跟光磊学Java编程";    StringBuilder content = new StringBuilder(str);    System.out.println("content.length() = " + content.length());  }

程序运行结果

2dd617b438db9a1e8791de26da686920.png

如果使用空字符串创建StringBuilder对象,通过源码得知,默认会开辟长度为16个字节的长度

   /**     * Constructs a string builder with no characters in it and an     * initial capacity of 16 characters.     */    @HotSpotIntrinsicCandidate    public StringBuilder() {        super(16);    } /**     * Creates an AbstractStringBuilder of the specified capacity.     */    AbstractStringBuilder(int capacity) {        if (COMPACT_STRINGS) {            value = new byte[capacity];            coder = LATIN1;        } else {            value = StringUTF16.newBytesFor(capacity);            coder = UTF16;        }    }

StringBuilder常用方法

在创建StringBuilder对象后就可以调用StringBuilder对象的方法。

123408df0a4ac9f8c0f31cbe66024d84.png
  1. 使用StringBuilder实现字符串拼接
  /**   * append():拼接任意类型的数据返回本身   */  @Test  public void testStringBuilderAppend(){    StringBuilder emptyString=new StringBuilder();    emptyString.append(2020);    emptyString.append("年");    StringBuilder result=emptyString.append("跟光磊学Java开发");    System.out.println(result);    System.out.println("result==emptyString = "+(result==emptyString));  }

程序运行结果
无论拼接多少次返回的都是同一个StringBuilder对象

effa408671fbb66bd88120c2fbb0c6d1.png
  1. 在指定的位置插入字符串
  /**   * insert():在指定的位置插入数据并返回本身   */  @Test  public void testStringBuilderInsert(){    StringBuilder emptyString=new StringBuilder();    emptyString.append("跟光磊学Java开发,");    emptyString.append("跟光磊学Linux运维");    emptyString.insert(11,"跟光磊学前端开发,");    System.out.println(emptyString);  }

程序运行结果

176ac80077f6a3d0ef1b211a5a0f773e.png
  1. 字符串反转
 /**   * reverse():反转字符串并返回   */  @Test  public void testStringBuilderReverse(){    StringBuilder helloWorld=new StringBuilder("界世好你");    StringBuilder reverseResult = helloWorld.reverse();    System.out.println("reverseResult==helloWorld = "+(reverseResult==helloWorld));    System.out.println(helloWorld);  }

程序运行结果

2e13ba787e374ab3aa07630a44a5c341.png
  1. StringBuilder和String对象的相互转换
  /**   * StringBuilder和String的相互转换   */  @Test  public void testStringBuilderToString(){    String str="HelloWorld";    //String转StringBuilder    StringBuilder content=new StringBuilder(str);    //StringBuilder转String    str=content.toString();  }
  1. 使用StringBuilder实现Arrays.toString()方法
 /**   * 使用StringBuilder实现Arrays.toString()方法   */  @Test  public void testStringBuilderAppendArray(){    int[] numbers=new int[]{1,2,4,5,7,8,9,6,3};    StringBuilder content = new StringBuilder("[");    for (int i = 0; i < numbers.length ; i++) {      if(i

程序运行结果

b1ab4724fa058807b55afe311b42d59a.png
  1. 使用链式编程实现字符串反转
/**   * 使用StringBuilder实现字符串反转   */  @Test  public void testStringBuilderReverseString(){    String str="发开avaJ学磊光跟";    String reverseStr=reverse(str);    System.out.println(reverseStr);  }  /**   * 定义一个字符串反转的方法返回元字符串   * @param str   * @return   */  public String reverse(String str){  // 链式编程    return new StringBuilder(str).reverse().toString();  }

程序运行结果

e6fa2a329ff04e0869415326e15daed8.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值