자바 시리즈 3의 기초를 통합 : 실제 전투, 더 원리 분석 및 소스 코드를 분석하는 기본에서 텍스트 문자열 일반적인 면접 질문을 알게!

디렉토리

기사의이 시리즈는 GitHub의의 "자바 인터뷰 가이드"창고에 나에게 드릴 것입니다, 더 흥미로운 콘텐츠를 내 창고보기로 이동하십시오

https://github.com/h2pl/Java-Tutorial

문제 아래는 스타 카자흐스탄 관광 명소처럼

제 먼저 내 개인 블로그에 출연 :

www.how2playlife.com

이 문서는 마이크로 채널 대중 번호가 자바 기술 돌팔이 [의] "자바 재단 시리즈 보웬을 강화"하는이 문서의 주제에 네트워크에서이 문서의 일부는 명확하고 철저하게 말을하고, 나는 기술 블로그 콘텐츠의 좋은 통합을 많이 생각, 침해, 저자에 문의하시기 바랍니다 경우 이는 좋은 블로그 게시물의 숫자를 언급했다. 전체 Java 기술 시스템의보다 완전한 이해, 자신을 형성하기 위해이 블로그 시리즈는 고급에 항목에서, 단계별로 자바의 기초를 배울하는 방법을 보여주고, 실제 전투를 시작합니다, 각 지점 뒤의 원칙을 실현하기 위해 자바 지식을 이해 지적 프레임 워크. 요약 및 학습 결과를 테스트하기 위해이 시리즈는 모든 지식 포인트 해당 인터뷰 질문을 제공하고 답변을 제안합니다.

이 기사의이 시리즈에 대한 어떤 제안 또는 질문이있는 경우, 공공 강과 호수 [] 자바 기술 저자에게 연락 할 수에 대한 우려도 할 수있는, 당신은이 블로그 시리즈의 작성 및 수정에 참여하실 수 있습니다.

[TOC]

문자열의 기초

자바 String 클래스

널리 자바 문자열에서 자바 프로그래밍에서 사용되는 문자열 객체에 속하는 자바 만들고 문자열을 조작하는 String 클래스를 제공합니다.

문자열 만들기

다음과 같이 쉬운 방법은 문자열을 만들 수 있습니다 :

문자열 인사 = "신인 코스";

코드에서 발생하는 문자열 상수, 값은 여기 "입니다 신인 튜토리얼 컴파일러는 값이 String 객체를 생성합니다", ".

그리고 다른 개체, 당신은 String 객체를 생성하는 키워드와 생성자를 사용할 수 있습니다.

String 클래스는 문자 배열 파라미터로서, 문자열을 초기화하는 다른 파라미터들을 제공 공법 11 종류가있다 :

StringDemo.java 파일 코드 :

public class StringDemo{    public static void main(String args[]){       char[] helloArray = { 'r', 'u', 'n', 'o', 'o', 'b'};       String helloString = new String(helloArray);         System.out.println( helloString );    } }复制代码

다음과 같은 결과를 컴파일 상기 예이다 :

runoob复制代码

참고 : 당신이 String 객체를 생성하면, 그 값은 (자세한 메모를 부분 구문 분석 참조) 변경 될 수 없도록 String 클래스는 불변이다.

당신이 문자열에 많은 수정을해야 할 경우에는 사용을 선택해야 StringBuffer를 &의 StringBuilder 클래스를 .

문자열 기본적인 사용법

String 객체를 생성하는 일반적인 방법

(1) 문자열 S1 = "mpptest"

(2) = S2 문자열 새로운 String ();

(3) 문자열 S3 = 새로운 문자열 ( "mpptest")

도 사용에서와 같이 문자열은 일반적으로, 특히 어머니의 요구, 방법을 사용

) (lenth () 문자열 () 수 charAt : 세 가지 방법을 사용하여

패키지 com.mpp.string; 공용 클래스 StringDemo1 {공공 정적 무효 메인 (문자열 []에 args) {// 문자열의 정의 문자열 STR은 = "하루 밤에 눈을 마실 수 있도록"하루 밤 눈이 마실 수 없습니다 " 더 컵 ";에서 System.out.println는 ("문자열의 길이가 없습니다 : "+의 str.length ()); 눈 단어 출력 수 charAt // 문자열 (INT 지수)에서 System.out.println (str.charAt ( 4)); // 날 촬영이 문자열에서 System.out.println (str.substring (2)); 2System.out.println (str.substring를 포함하는 문자열의 마지막까지 처음부터 촬영 // index2 (2, 4)) 2를 포함하는 서브 - 스트링 2~4 찍은 // 지수}}없이 4 꼬리 치료를 포함하지 않는다

() 같이 IndexOf () lastIndexOf에서도 : 두 가지 방법을 사용하면, 문자 또는 문자열 문자열의 첫 번째 / 마지막으로 나타나는 위치를 찾을 수

패키지 com.mpp.string; 공용 클래스 StringDemo2 {공공 정적 무효 메인 (문자열 []에 args) {문자열 str을 = 새로운 문자열 ( "자오 고객 꾸밈 후 잉 후 잉 우 훅 서리 밖으로"); // 문자열 후 찾기 성격 후 잉 ","// 문자열을 찾기 : ()에서 System.out.println의 첫 번째 항목 "+ str.indexOf ("후 ""후 "문자열의 첫 번째 발생에 위치)"의 위치 문자열 ( "문자열"+ str.indexOf ( "후 잉")의 최초 발생시 "잉 후"위치)의 처음 나타나는 위치에서 System.out.println; 문자열 후 찾기 // 마지막 시간에서 System.out.println (str.lastIndexOf ( "후")를) 표시합니다; // ((표시 문자열의 마지막에서 System.out.println "후 잉"위치 str.lastIndexOf을 문자열 찾기 "후 잉")); // 같이 IndexOf 행은 "미스"에서 System.out.println (str.indexOf ( "우"의 첫번째 발생을 찾기 위해,도 5의 위치로, 5));}}

문자열과 바이트 배열 간의 변환

패키지 com.mpp.string; 수입 java.io.UnsupportedEncodingException; Public 클래스 StringDemo3 {공공 정적 무효 메인 (문자열 []에 args) {예외 : UnsupportedEncodingException를 발생 // 문자열과 바이트 배열 = 새로운 문자열 사이의 문자열 str을 상호 변환 ( " "); // 바이트 배열로 문자열 변환 및 바이트 [] ARRS의 =의 str.getBytes (를 인쇄"와 같은 유성 등 hhhabc 은백색 말 사행 다, 따른 안장 GBK ") (I에게 = 0 인터넷 용; I) {시스템 .out.print (ARRS [I])} // 바이트 배열로 문자열을 변환에서 System.out.println (); 문자열 STR1 = 새로운 캐릭터 (ARRS "GBK"); // 일치하는 문자 집합 그렇지 않으면, 왜곡에서 System.out.println (STR1);}}

== 오퍼레이터 간의 차이는 동일하다 :

주소를 가리키는 인용 및 참조에 지적

패키지 com.mpp.string; 공용 클래스 StringDemo5 {공공 정적 무효 메인 (문자열 []에 args) {문자열 STR1 = 'MPP', 스트링 (STR2) = 'MPP'; 문자열 STR3 = 새로운 문자열 ( "MPP ');

    System.out.println(str1.equals(str2)); //true  内容相同
    System.out.println(str1.equals(str3));   //true  内容相同
    System.out.println(str1==str2);   //true   地址相同
    System.out.println(str1==str3);   //false  地址不同复制代码

}}

문자열의 불변성

String 객체가 생성되면, 불변이다, 수정할 수 없습니다

사실, 소위 수정, 새로운 객체를 만드는 것입니다 같은 메모리 공간을 가리키는

위 그림은, 헬로, imooc에 메모리 곳 imooc 공간 만 점에 더 이상 포인트를 S1 없습니다

문자열 연결

@Test
public void contact () {
    //1连接方式
    String s1 = "a";
    String s2 = "a";
    String s3 = "a" + s2;
    String s4 = "a" + "a";
    String s5 = s1 + s2;
    //表达式只有常量时,编译期完成计算
    //表达式有变量时,运行期才计算,所以地址不一样
    System.out.println(s3 == s4); //f
    System.out.println(s3 == s5); //f
    System.out.println(s4 == "aa"); //t

}复制代码

차이 문자열, 문자열 빌더 및 문자열 버퍼

문자열 때문에 불변의 다른 특성이 마지막으로 선언이 속성을 해시 할뿐만 아니라 자바 기반의 중요한 클래스, 또한 일반적인 구현 불변의 String 클래스가 선언 최종 클래스, 그래서 시간은 스플 라이스와 같은 문자열을 생성합니다 많은 쓸모없는 중간 오브젝트, 또는 자주 이러한 작업을 수행 할 경우 성능에 영향을 미친다.

큰 클래스의 StringBuffer 문자열 연결이 중간 개체를 제공하기 위해 많은 문제를 야기 해결하기 위해, 문자열 또는 지정된 위치에 존재하는 서열의 마지막에 추가 할 수 있고,이 메소드 APPEND을 제공하고 추가되고, 그것은 본질적으로 보안 스레드가 될 수있다 문자의 순서를 수정, 모든 데이터 수정 방법은 동기화 추가됩니다. 그러나 보안 스레드를 보장하는 것은의 가격 대비 성능의 필요성이다.

많은 경우에 우리는 스레드 안전 문자열 연결 작업을하지 않아도,이 시간의 StringBuilder 데뷔, 모두 StringBuilder는 JDK1.5 자료이며, 본질적으로 StringBuffer와 아무런 차이가 없습니다, 그것은 오버 헤드를 줄이고, 보증 스레드 안전의 일부를 제거하는 것입니다 .

StringBuffer를 모두와의 StringBuilder AbstractStringBuilder는 하부층이 수정 문자 배열을 사용하는 것이다 상속 (이하 JDK 9 바이트 배열).

당신이 예측할 수 있다면 우리는, 문자열 연결이 많은 경우 크기가 여러 확장의 오버 헤드를 피하기 위해 새로운 StringBuffer와의 용량 또는 StringBuilder의 시간을 설정하는 가장 좋은 것입니다. 확장은 원래의 배열을 포기뿐만 아니라 배열의 배열의 새 복사본을 생성합니다.

우리는 일반적으로, 일반적으로 정말 예를 들어, 너무 많이 고민 할 필요가없는 문자열 연결의 소량을 개발

문자열 STR = "AA"+ "BB"+ "CC";

이 문자열 변수, 컴파일러 단계 직접 합성 "AABBCC을"좋아, 다음 (정수 풀 아래 이야기합니다) 문자열 상수 풀을 볼 수있다, 아니, 상수 풀을 생성하지 않는, 또한 직접 참조가 존재한다, 참조를 반환합니다.

밴드가 변수 인 경우, 사실,별로 영향, JVM은 우리가 최적화하는 데 도움이됩니다.

자주 변경되지 않는 문자열 문자열을 사용하여 비즈니스 시나리오 1 개 우선 순위 (코드 더 명확하고 간결)가 발생합니다. 상수 선언 된 바와 같이, 문자열 처리 소량 (접합부는, 등을 제거).

(2)는 단일 스레드의 경우에, 캐릭터를 조작하는 다수의 스트링은 StringBuilder의 작동에 사용하는 경우. 당신은 "+"문자열을 사용할 수 있지만 바느질의 사용은 쓸모없는 중간 오브젝트, 공간이 소요되는 비효율적 인 실행의 많은 피하기 위해 (새로 생성 된 객체를, 객체는 많은 시간 복구 소요). JSON 포장 등.

도 3은 멀티 스레드의 경우에, 캐릭터 동작의 경우 다수가 StringBuffer에 사용되어야하는 경우. 는 HTTP 매개 변수 구문 분석 및 포장.

String 클래스의 소스 코드 분석

인턴의 문자열 유형

public void intern () {
    //2:string的intern使用
    //s1是基本类型,比较值。s2是string实例,比较实例地址
    //字符串类型用equals方法比较时只会比较值
    String s1 = "a";
    String s2 = new String("a");
    //调用intern时,如果s2中的字符不在常量池,则加入常量池并返回常量的引用
    String s3 = s2.intern();
    System.out.println(s1 == s2);
    System.out.println(s1 == s3);
}复制代码

등호의 문자열 유형

//字符串的equals方法
//    public boolean equals(Object anObject) {
//            if (this == anObject) {
//                return true;
//            }
//            if (anObject instanceof String) {
//                String anotherString = (String)anObject;
//                int n = value.length;
//                if (n == anotherString.value.length) {
//                    char v1[] = value;
//                    char v2[] = anotherString.value;
//                    int i = 0;
//                    while (n-- != 0) {
//                        if (v1[i] != v2[i])
//                            return false;
//                        i++;
//                    }
//                    return true;
//                }
//            }
//            return false;
//        }复制代码

StringBuffer와 和의 StringBuilder

바닥층은 변수 문자 배열 값이 상위 클래스를 상속이고

/**

- The value is used for character storage.
  */
  char[] value;
  初始化容量为16

/**

- Constructs a string builder with no characters in it and an
- initial capacity of 16 characters.
  */
  public StringBuilder() {
  super(16);
  }
  这两个类的append方法都是来自父类AbstractStringBuilder的方法

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}
@Override
public StringBuilder append(String str) {
    super.append(str);
    return this;
}

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}复制代码

방법을 추가

StringBuffer를 스레드 안전을 보장하기 위해 동기화 된 키워드를 수정하는 문자열의 추가와 관련된 대부분의 작업에 효율이 낮다.

예를 들어 + 연산자를 사용하여 문자열 유형

문자열 A = "A"

A = A + a 및 문자열이 많이 사용을 추가 할 때, 실제로는, 다음 tostring와 메쏘드 호출의 리턴을 추가하여 StringBuilder에 제 1 패키지가, StringBuilder의 인스턴스를 다량 생성 할 때, 매우 낭비 본 모두 StringBuilder 시간 대신 문자열을 사용해야합니다.

확장

Append 메서드에서 함수에 대한 호출을 참고

ensureCapacityInternal은 (LEN + 카운트) 프로세스가 산출된다 APPEND 공간 적절한 후 불충분 확장 원한다면 될

public void ensureCapacity(int minimumCapacity) {
    if (minimumCapacity > 0)
        ensureCapacityInternal(minimumCapacity);
}
private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}复制代码

새로운 값은 상기 어레이의 길이의 확장의 문자열 길이보다 크면

전개 후 길이는 일반적으로 회 일본어 + 2이고;

팽창 후의 길이지지 JVM MAX의 어레이의 최대 길이를 초과하면 ARRAY의 크기.

두 가지 경우가 고려된다

이상 최대 INT보다 새 문자열 경우, 예외가 발생하거나, 새로운 배열의 배열 길이의 최대 길이로 직접 사용.

private int hugeCapacity(int minCapacity) {
    if (Integer.MAX_VALUE - minCapacity < 0) { // overflow
        throw new OutOfMemoryError();
    }
    return (minCapacity > MAX_ARRAY_SIZE)
        ? minCapacity : MAX_ARRAY_SIZE;
}
复制代码

삭제

삭제 이러한 두 가지 유형 :

우리는 부모 클래스를 삭제하려면 삭제 방법을 요구하고있다

public AbstractStringBuilder delete(int start, int end) {
    if (start < 0)
        throw new StringIndexOutOfBoundsException(start);
    if (end > count)
        end = count;
    if (start > end)
        throw new StringIndexOutOfBoundsException();
    int len = end - start;
    if (len > 0) {
        System.arraycopy(value, start+len, value, start, count-end);
        count -= len;
    }
    return this;
}
复制代码

사실, 나머지 문자는 다시 문자 배열 값으로 복사됩니다.

다음은 배열을 복사하는 System.arraycopy에 사용, 속도가 상대적으로 빠르다

System.arraycopy에 방법

켜 거의 알고 :

주류 고성능 JVM (핫스팟 VM 시스템, IBM J9 VM 시스템,하는 JRockit 시스템 등)에서,이 System.arraycopy에 고려 될 수있다 () 복사 배열 안정적이고 효율적인 경우 - 효율이 충분하지 않은 경우가 발견하는 경우, 성능을보고하십시오 버그는 확실히 곧 개선 될 것입니다.

java.lang.System.arraycopy () 메소드는 자바 코드에서 네이티브 메소드로 선언된다. 그래서 JVM JNI에 의해 달성 가장 순진한 구현은 네이티브 코드에서 호출합니다.

불변의 문자열

문자열의 불변성에 대해, 여기에 좋은 답변을 켜

무엇 불변인가?

불변 문자열은 두 번째 "abcedl"원래 메모리 어드레스의 데이터를 수정하지 할당 된 기존의 문자열 "ABCD"로 도시 된 바와 같이, 심플하지만 다시 점 새로운 객체, 새로운 어드레스.

문자열 관계와 JVM

여기에서 우리는 자바 스택, 자바 힙, 메소드 영역 및 정수 풀에서 이해 :

자바 스택 (개인 데이터 영역을 스레드) :

    每个Java虚拟机线程都有自己的Java虚拟机栈,Java虚拟机栈用来存放栈帧,每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
复制代码

Java 힙 (스레드 공유 데이터 영역) :

   在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配。
复制代码

메소드 영역 (스레드가 공유 된 데이터 영역)

   方法区在虚拟机启动的时候被创建,它存储了每一个类的结构信息,例如运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容、还包括在类、实例、接口初始化时用到的特殊方法。在JDK8之前永久代是方法区的一种实现,而JDK8元空间替代了永久代,永久代被移除,也可以理解为元空间是方法区的一种实现。
复制代码

상수 풀 (thread에 공유 데이터 영역) :

    常量池常被分为两大类:静态常量池和运行时常量池。

    静态常量池也就是Class文件中的常量池,存在于Class文件中。

    运行时常量池(Runtime Constant Pool)是方法区的一部分,存放一些运行时常量数据。
复制代码

다음은 문자열 상수 풀 것을 이해하는 것이 중요합니다 :

    字符串常量池存在运行时常量池之中(在JDK7之前存在运行时常量池之中,在JDK7已经将其转移到堆中)。

    字符串常量池的存在使JVM提高了性能和减少了内存开销。

    使用字符串常量池,每当我们使用字面量(String s=”1”;)创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就将此字符串对象的地址赋值给引用s(引用s在Java栈中)。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中,并将此字符串对象的地址赋值给引用s(引用s在Java栈中)。
复制代码

    使用字符串常量池,每当我们使用关键字new(String s=new String(”1”);)创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么不再在字符串常量池创建该字符串对象,而直接堆中复制该对象的副本,然后将堆中对象的地址赋值给引用s,如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中,然后在堆中复制该对象的副本,然后将堆中对象的地址赋值给引用s。
复制代码

왜 문자열 불변?

JDK 오픈 소스, java.lang.String 클래스에 손을 처음 세 줄은 다음과 같이 기록됩니다

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {   
  /** String本质是个char数组. 而且用final关键字修饰.*/     
private final char value[];  ...  ...
 } 
复制代码

먼저 String 클래스는 문자열 상속 될 수 없습니다 나타내는 최종 키워드로 수정됩니다. 다음 봐 주요 부재 필드 값 문자열 클래스는 문자 [] 배열이지만, 최종적으로 수정.

최종 수정 필드 후 변경 결코 만들 수 있습니다. 어떤 사람들은 그것을하지 않았다,이 이야기는 이상하다고 생각합니다. 값은 불변이지만,이므로 만이 어드레스의 기준 값은 변경되지 않는다. 배열은 배열 변수라는 사실을 중지 할 수 없습니다.

어레이 데이터 구조 일견도.

스택 단지 참조 힙 힙 어레이의 구조체 배열 변수이다.

이 말을 제외하고는 값의 최종 수정과 String 클래스는 불변의 스택 참조 주소 값이라고합니다. 그는 배열 데이터의 더미 자체 불변 말을하지 않았다. 다음 예를 살펴 보겠습니다,

final int[] value={1,2,3} ;
int[] another={4,5,6};
 value=another;    //编译器报错,final不可变 value用final修饰,编译器不允许我把value指向堆区另一个地址。
但如果我直接对数组元素动手,分分钟搞定。

 final int[] value={1,2,3};
 value[2]=100;  //这时候数组里已经是{1,2,100}   所以String是不可变,关键是因为SUN公司的工程师。
 在后面所有String的方法里很小心的没有去动Array里的元素,没有暴露内部成员字段。private final char value[]这一句里,private的私有访问权限的作用都比final大。而且设计师还很小心地把整个String设成final禁止继承,避免被其他人继承后破坏。所以String是不可变的关键都在底层的实现,而不是一个final。考验的是工程师构造数据类型,封装数据的功力。 
复制代码

불변의 이점은 무엇입니까?

가장 간단한 이유는 안전을위한 것입니다. 다시 불변 함수 appendStr String 매개 변수 플러스 일부 "BBB"()의 복귀 후, (일부 비평가들은 예 충분히 명확 지금 당장 쓸 수없는 반응) 다음과 같은 시나리오 봐. appendSb ()는 변수 뒷면의 StringBuilder 플러스 "BBB"에 대한 책임이 있습니다.

다음은 문자열의 불변성을 요약 한 것입니다.

1 수정 된 최종 일류만을 보장은 상속 될 수 없습니다, 그리고 힙이 클래스 주소의 목적은 변경되지 않습니다.

2하지만 그가 다른 목적을 가리킬 수 등 자체가 변경 될 수있는 문자열 오브젝트 참조를 보유하고있다.

(3) 최종 수정 문자 배열은 참조 문자 배열을 바꿀 수 없도록. 그러나, 그 값은 [0] = "A"문자에 의해 변형 될 수있다. 그러나,이 방법은이 작업을 완료하기 위해 내부 문자열을 제공하지 않습니다, 문자열 코드 및 액세스 제어에 따라 불변의 패키지입니다.

예를 들면

final class Fi {
    int a;
    final int b = 0;
    Integer s;

}
final char[]a = {'a'};
final int[]b = {1};
@Test
public void final修饰类() {
    //引用没有被final修饰,所以是可变的。
    //final只修饰了Fi类型,即Fi实例化的对象在堆中内存地址是不可变的。
    //虽然内存地址不可变,但是可以对内部的数据做改变。
    Fi f = new Fi();
    f.a = 1;
    System.out.println(f);
    f.a = 2;
    System.out.println(f);
    //改变实例中的值并不改变内存地址。
复制代码

Fi ff = f;
//让引用指向新的Fi对象,原来的f对象由新的引用ff持有。
//引用的指向改变也不会改变原来对象的地址
f = new Fi();
System.out.println(f);
System.out.println(ff);

}
复制代码

FA 이해 될 위치 수정 [0] = "A"와 같은 작업을 CHAR있다. 값만 변화 데이터는, 상기 메모리 값을 변경하지 않는다.

문자열 일반적으로 사용되는 도구

문제 설명 많은 우리가 문자열 작업을 많이 수정해야 시간 및 이러한 작업없이의 JDK / JRE의 사전 설정, 그래서 우리는 아파치 - 평민 구성 요소를 생각했지만, 완전히, 너무 많은 우리 기업의 요구를 커버 할 수 자신의 포인트 코드를 작성하거나 시간은 다음과 쓴 아파치 - 평민에 따라 몇 가지 일반적인 구성 요소입니다 :

MAVEN依赖
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>${commons-lang3.version}</version>
 </dependency>
复制代码

코드 성과

public class StringUtils extends org.apache.commons.lang3.StringUtils {

/** 值为"NULL"的字符串 */
private static final String NULL_STRING = "NULL";

private static final char SEPARATOR = '_';
复制代码

/**
 * 满足一下情况返回true<br/>
 * ①.入参为空
 * ②.入参为空字符串
 * ③.入参为"null"字符串
 *
 * @param string 需要判断的字符型
 * @return boolean
 */
public static boolean isNullOrEmptyOrNULLString(String string) {
    return isBlank(string) || NULL_STRING.equalsIgnoreCase(string);
}

/**
 * 把字符串转为二进制码<br/>
 * 本方法不会返回null
 *
 * @param str 需要转换的字符串
 * @return 二进制字节码数组
 */
public static byte[] toBytes(String str) {
    return isBlank(str) ? new byte[]{} : str.getBytes();
}

/**
 * 把字符串转为二进制码<br/>
 * 本方法不会返回null
 *
 * @param str     需要转换的字符串
 * @param charset 编码类型
 * @return 二进制字节码数组
 * @throws UnsupportedEncodingException 字符串转换的时候编码不支持时出现
 */
public static byte[] toBytes(String str, Charset charset) throws UnsupportedEncodingException {
    return isBlank(str) ? new byte[]{} : str.getBytes(charset.displayName());
}

/**
 * 把字符串转为二进制码<br/>
 * 本方法不会返回null
 *
 * @param str     需要转换的字符串
 * @param charset 编码类型
 * @param locale  编码类型对应的地区
 * @return 二进制字节码数组
 * @throws UnsupportedEncodingException 字符串转换的时候编码不支持时出现
 */
public static byte[] toBytes(String str, Charset charset, Locale locale) throws UnsupportedEncodingException {
    return isBlank(str) ? new byte[]{} : str.getBytes(charset.displayName(locale));
}

/**
 * 二进制码转字符串<br/>
 * 本方法不会返回null
 *
 * @param bytes 二进制码
 * @return 字符串
 */
public static String bytesToString(byte[] bytes) {
    return bytes == null || bytes.length == 0 ? EMPTY : new String(bytes);
}

/**
 * 二进制码转字符串<br/>
 * 本方法不会返回null
 *
 * @param bytes   二进制码
 * @param charset 编码集
 * @return 字符串
 * @throws UnsupportedEncodingException 当前二进制码可能不支持传入的编码
 */
public static String byteToString(byte[] bytes, Charset charset) throws UnsupportedEncodingException {
    return bytes == null || bytes.length == 0 ? EMPTY : new String(bytes, charset.displayName());
}

/**
 * 二进制码转字符串<br/>
 * 本方法不会返回null
 *
 * @param bytes   二进制码
 * @param charset 编码集
 * @param locale  本地化
 * @return 字符串
 * @throws UnsupportedEncodingException 当前二进制码可能不支持传入的编码
 */
public static String byteToString(byte[] bytes, Charset charset, Locale locale) throws UnsupportedEncodingException {
    return bytes == null || bytes.length == 0 ? EMPTY : new String(bytes, charset.displayName(locale));
}

/**
 * 把对象转为字符串
 *
 * @param object 需要转化的字符串
 * @return 字符串, 可能为空
 */
public static String parseString(Object object) {
    if (object == null) {
        return null;
    }
    if (object instanceof byte[]) {
        return bytesToString((byte[]) object);
    }
    return object.toString();
}

/**
 * 把字符串转为int类型
 *
 * @param str 需要转化的字符串
 * @return int
 * @throws NumberFormatException 字符串格式不正确时抛出
 */
public static int parseInt(String str) throws NumberFormatException {
    return isBlank(str) ? 0 : Integer.parseInt(str);
}

/**
 * 把字符串转为double类型
 *
 * @param str 需要转化的字符串
 * @return double
 * @throws NumberFormatException 字符串格式不正确时抛出
 */
public static double parseDouble(String str) throws NumberFormatException {
    return isBlank(str) ? 0D : Double.parseDouble(str);
}

/**
 * 把字符串转为long类型
 *
 * @param str 需要转化的字符串
 * @return long
 * @throws NumberFormatException 字符串格式不正确时抛出
 */
public static long parseLong(String str) throws NumberFormatException {
    return isBlank(str) ? 0L : Long.parseLong(str);
}

/**
 * 把字符串转为float类型
 *
 * @param str 需要转化的字符串
 * @return float
 * @throws NumberFormatException 字符串格式不正确时抛出
 */
public static float parseFloat(String str) throws NumberFormatException {
    return isBlank(str) ? 0L : Float.parseFloat(str);
}

/**
 * 获取i18n字符串
 *
 * @param code
 * @param args
 * @return
 */
public static String getI18NMessage(String code, Object[] args) {
    //LocaleResolver localLocaleResolver = (LocaleResolver) SpringContextHolder.getBean(LocaleResolver.class);
    //HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
    //Locale locale = localLocaleResolver.resolveLocale(request);
    //return SpringContextHolder.getApplicationContext().getMessage(code, args, locale);
    return "";
}

/**
 * 获得用户远程地址
 *
 * @param request 请求头
 * @return 用户ip
 */
public static String getRemoteAddr(HttpServletRequest request) {
    String remoteAddr = request.getHeader("X-Real-IP");
    if (isNotBlank(remoteAddr)) {
        remoteAddr = request.getHeader("X-Forwarded-For");
    } else if (isNotBlank(remoteAddr)) {
        remoteAddr = request.getHeader("Proxy-Client-IP");
    } else if (isNotBlank(remoteAddr)) {
        remoteAddr = request.getHeader("WL-Proxy-Client-IP");
    }
    return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
}

/**
 * 驼峰命名法工具
 *
 * @return toCamelCase(" hello_world ") == "helloWorld"
 * toCapitalizeCamelCase("hello_world") == "HelloWorld"
 * toUnderScoreCase("helloWorld") = "hello_world"
 */
public static String toCamelCase(String s, Locale locale, char split) {
    if (isBlank(s)) {
        return "";
    }

    s = s.toLowerCase(locale);

    StringBuilder sb = new StringBuilder();
    for (char c : s.toCharArray()) {
        sb.append(c == split ? Character.toUpperCase(c) : c);
    }

    return sb.toString();
}

public static String toCamelCase(String s) {
    return toCamelCase(s, Locale.getDefault(), SEPARATOR);
}

public static String toCamelCase(String s, Locale locale) {
    return toCamelCase(s, locale, SEPARATOR);
}

public static String toCamelCase(String s, char split) {
    return toCamelCase(s, Locale.getDefault(), split);
}

public static String toUnderScoreCase(String s, char split) {
    if (isBlank(s)) {
        return "";
    }

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        boolean nextUpperCase = (i < (s.length() - 1)) && Character.isUpperCase(s.charAt(i + 1));
        boolean upperCase = (i > 0) && Character.isUpperCase(c);
        sb.append((!upperCase || !nextUpperCase) ? split : "").append(Character.toLowerCase(c));
    }

    return sb.toString();
}

public static String toUnderScoreCase(String s) {
    return toUnderScoreCase(s, SEPARATOR);
}

/**
 * 把字符串转换为JS获取对象值的三目运算表达式
 *
 * @param objectString 对象串
 *                     例如:入参:row.user.id/返回:!row?'':!row.user?'':!row.user.id?'':row.user.id
 */
public static String toJsGetValueExpression(String objectString) {
    StringBuilder result = new StringBuilder();
    StringBuilder val = new StringBuilder();
    String[] fileds = split(objectString, ".");
    for (int i = 0; i < fileds.length; i++) {
        val.append("." + fileds[i]);
        result.append("!" + (val.substring(1)) + "?'':");
    }
    result.append(val.substring(1));
    return result.toString();
}
复制代码

}
复制代码

참조 기사

https://blog.csdn.net/qq_34490018/article/details/82110578https://www.runoob.com/java/java-string.htmlhttps://www.cnblogs.com/zhangyinhua/p/7689974.htmlhttps : //blog.csdn.net/sinat_21925975/article/details/86493248https://www.cnblogs.com/niew/p/9597379.html

마이크로 채널 공개 수

자바 강과 호수

SSM, SpringBoot : 내 실시간으로 업데이트 된 기사 및 건조 공유에 초점을하려는 경우, 당신은 강과 호수의 내 공개 수에 초점을 맞출 수 있습니다] [자바 기술 자바, 기술 엔지니어 알리 역, 저자 황 경사는 자바 관련 기술에 초점을 맞춘 , MySQL은, 분산, 미들웨어, 클러스터, 리눅스, 네트워크, 때때로 점 도커, ELK 말하기, 멀티 스레드뿐만 아니라 건조 제품 및 기술은 전체 자바 스택 개발에 최선을 다하고 학습 경험을 공유!

자바 엔지니어 학습 리소스를 필요 : 일부 자바 엔지니어 일반적인 학습 자원을, 대중의 관심의 수, 배경 키워드 응답 "자바" 어떤 루틴을 무료로 얻을 수 있습니다.

내 공개 수

개인 공공 번호 : 황 경사

저자는 JAVA 백엔드 기술 스택을 전문으로, 석사 985, 개미 황금 드레스 JAVA 엔지니어 : SpringBoot는, MySQL은, 분산, 미들웨어, 서비스뿐만 아니라 투자 은행의 지점을 이해하고, 가끔 말하기 포인트 알고리즘과 컴퓨터의 이론적 기초를 학습을 유지 쓰기, 평생 학습의 힘을 믿습니다!

프로그래머 3T 기술 학습 자원 : 자원 마구 기술을 학습 일부 프로그래머들은 대중의 관심의 수는, 배경 키워드 대답 "데이터" 어떤 루틴을 무료로 얻을 수 있습니다.

추천

출처juejin.im/post/5d8b57545188253e5445311a