수업내용/Java

[2022.09.27.화] Object 클래스, String 클래스

주니어주니 2022. 9. 28. 00:56

 

<자바 API  중 java.lang(가장 기본적인 클래스들 제공)의 클래스들 살펴보기> 

 

1. Object 

  • java.lang패키지에 속하는 클래스
  • 배열을 포함한 모든 객체의 최상위 부모클래스다.
  • 명시적으로 extends를 사용해서 부모클래스를 지정하지 않으면 무조건 extends Object로 간주된다.
  • Object의 모든 메소드는 모든 클래스가 상속받는다.
  • 모든 객체는 Object의 메소드를 사용할 수 있다.
  • Object에는 객체와 관련된 필수 기능들이 구현되어 있다.

 

Object 클래스 주요 메소드

  • boolean equals(Object obj)
    • 현재 객체와 전달받은 객체가 동일한 객체인지 여부를 반환한다.
    • 객체들의 주소값(참조값)을 비교한다.
    • 재정의 가능
    • 원래 동일성(주소값까지 동일) 비교인데, 동등성(객체의 값만 동일)을 비교할 수 있도록 재정의 
  • int hashCode()
    • 현재 객체의 해시코드값을 반환한다. (해시코드: 객체가 생성될 때 임의로 부여되는 숫자값) 
    • 재정의 가능
  • String toString()
    • 현재 객체에 대한 간단한 정보를 제공한다.
    • 클래스이름@16진수해시코드
    • 재정의 가능
    • 객체의 멤버변수가 갖고있는 값을 반환하도록 재정의
  • Class<?> getClass()
    • 현재 객체에 대한 설계도(클래스정보) 정보를 제공한다.
  • Object clone()
    • 현재 객체를 복제한 복사본을 생성해서 제공한다.

 

 

* final 키워드 (클래스, 메소드, 변수) 

 

public final class Sample { 

}
- final이 정의된 클래스는 상속받을 수 없다.
- 상속 금지 

public class Sample {
               public final void test1( ) {
                              수행문;
                              수행문;
               }
               - final이 정의된 메소드는 하위클래스에서 재정의할 수 없다.
               - 재정의 금지 (getClass(), notify(), wait())  

               public void test2( ) {
                              final int x = 10;
                              - final이 정의된 변수는 값을 변경할 수 없다.
                              - 값 변경 금지 
               }
}

 

 

 

1-0. Object의 hashcode() 메소드 

  • int hashcode() - 객체의 해시코드값을 반환한다. (객체가 같으면 해시코드 값도 같음) 
public class Contact  { 

	private String name;
	private String email;
	private String phone;
	
	public Contact() {}
	public Contact(String name, String phone, String email) {
		this.name = name; 
		this.email = email;
		this.phone = phone;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}

 

public class ContactApp {

	public static void main(String[] args) {
		Contact c1 = new Contact("김유신", "010-1111-1111", "kim@naver.com");
		Contact c2 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");
		Contact c3 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");
		 
		System.out.println("### c1,c2 참조변수가 참조하는 Contact객체의 해시코드 확인하기");
		System.out.println(c1.hashCode());
		System.out.println(c2.hashCode());
		System.out.println(c3.hashCode());	//이름을 기준으로 해시코드 만드는것으로 설정했기 때문에 해시코드가 똑같다고 나옴

 

### c1,c2 참조변수가 참조하는 Contact객체의 해시코드 확인하기
44498463
43752720
43752720

 

 

 

1-1. Object의 toString() 메소드

  • toString()
    • 참조변수가 참조하는 객체에 대한 간단한 설명을 반환한다.
      패키지명.클래스 이름@16진수 해시코드값 (해시코드를 16진수로 바꾼 것)

    • toString메소드는 final 연산자가 붙지 않기 때문에, 메소드 재정의 가능!
      재정의하지 않으면, 원하는 값을 출력하기 어려움
      String str = new String("abc"); 
      System.out.println(str);                   // str이 가리키는 객체의 주소값이 아닌, 문자열이 출력됨
  • String toString()
    • 객체의 멤버변수값으로 구성된 문자열을 반환하도록 toString() 메소드를 재정의하는 경우가 많다. 
    • Obeject의 toString()을 재정의하는 대표적인 예
      - String toString() : String 클래스는 String객체가 가지고 있는 문자열을 반환하도록 재정의했다.
        Date toString() : Date 클래스는 Date객체의 현재 날짜와 시간 정보를 문자열로 반환하도록 재정의했다. 

 

<Object toString (메소드 재정의 전)>

 

-Contact 클래스

public class Contact {

	private String name;
	private String email;
	private String phone;
	
	public Contact() {}
	public Contact(String name, String phone, String email) {
		this.name = name; 
		this.email = email;
		this.phone = phone;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}

-ContactApp 클래스

public class ContactApp {

	public static void main(String[] args) {
		Contact c1 = new Contact("김유신", "010-1111-1111", "kim@naver.com");
		Contact c2 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");
		Contact c3 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");

		System.out.println("### c1,c2 참조변수가 참조하는 Contact객체의 정보를 문자열로 반환하기");
		System.out.println(c1.toString());
		System.out.println(c2.toString());
		System.out.println(c1);			// = System.out.println(c1.toString());
		System.out.println(c2);			// = System.out.println(c2.toString());
		
		String str = new String("abc");		// String은 재정의되기 때문에(final이 없음)
		System.out.println(str);		// str이 가리키는 객체의 주소값이 아니라, 문자열이 반환됨

 

### c1,c2 참조변수가 참조하는 Contact객체의 정보를 문자열로 반환하기
day18.Contact@626b2d4a
day18.Contact@5e91993f
day18.Contact@626b2d4a
day18.Contact@5e91993f
abc

 

--> 메소드를 재정의하지 않으면, 원하는 값을 얻을 수 없음. (객체의 정보가 반환되어버림)

 

 

 

<toString 메소드 재정의>

 

-Contact 클래스

	// Object의 toString() 메소드를 재정의하기
	// Contact객체의 멤버변수에 저장된 값으로 문자열을 생성해서 반환하도록 재정의 
	@Override
	public String toString() {
		return "Contact [name=" + name + ", email=" + email + ", phone=" + phone + "]";
	}

-ContactApp 는 그대로 

public class ContactApp {

	public static void main(String[] args) {
		Contact c1 = new Contact("김유신", "010-1111-1111", "kim@naver.com");
		Contact c2 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");
		Contact c3 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");

		System.out.println("### c1,c2 참조변수가 참조하는 Contact객체의 정보를 문자열로 반환하기");
		System.out.println(c1.toString());
		System.out.println(c2.toString());
		System.out.println(c1);			// = System.out.println(c1.toString());
		System.out.println(c2);			// = System.out.println(c2.toString());
		
		String str = new String("abc");		// String은 재정의되기 때문에(final이 없음)
		System.out.println(str);		// str이 가리키는 객체의 주소값이 아니라, 문자열이 반환됨

-실행결과 

### c1,c2 참조변수가 참조하는 Contact객체의 정보를 문자열로 반환하기
Contact [name=김유신, email=kim@naver.com, phone=010-1111-1111]
Contact [name=강감찬, email=kang@naver.com, phone=010-2222-2222]
Contact [name=김유신, email=kim@naver.com, phone=010-1111-1111]
Contact [name=강감찬, email=kang@naver.com, phone=010-2222-2222]
abc

 

 

 

1-2. Object의 equals() 메소드

 

public boolean equals(Object obj) { 
           return ( this == obj );
}

 

  • equals(Object obj)  -- (재정의 전) 
    • equals(Object other)를 실행하는 객체와 매개변수로 전달받은 객체가 동일한 객체인지 여부를 반환
    • 두 객체의 주소값(참조값)을 비교
    • 동일성을 검사 (아예 주소값까지 같은 객체인지)
    • 함수 매개변수 타입이 Object -> 모든 객체가 매개값이 될 수 있음을 의미
  • boolean equals(Object obj)  -- (재정의 후) 
    • 원래 동일성 비교(주소값 비교)인데, 동등성 비교(객체의 값 비교)할 수 있도록 재정의
    • Object의 equals() 메소드를 재정의한 대표적인 예
      - String 클래스의 equals() 메소드
        · 객체가 서로 다르더라도, 객체가 갖고 있는 문자열이 같으면 true 반환 (동등성 비교)
          (Object의 equals는 동일성, String의 equals는 동등성)
        · equals를 재정의하지 않으면 동일성을 비교해버림
        · String객체의 equals()메소드가 객체의 주소값이 아닌, 논리값을 비교할 수 있는 이유는
          String클래스가 Object의 equals()메소드를 재정의해서 문자열 비교로 변경했기 때문 
  • equals 메소드를 재정의할 때는, hashcode()와 equals() 두 개를 재정의해야 함  
    • 오른쪽 버튼 -> sourcecode -> generate hashcode() and equals() 
    • 먼저 hashCode()를 통해서 두 객체가 동일한지 빠르게 확인
      ( 서로 다른 객체는 해시코드가 무조건 달라 (해시코드가 다르면 equals를 비교할 필요도 없음) ) 
    • hashCode()가 같으면 equals()를 통해서 재비교 
      ( 단순히 비교면 equals만 있어도 되는데, 둘다 true여야 진짜 동등한 객체라고 인정 ) 
public class Contact  { 

	private String name;
	private String email;
	private String phone;
	
	public Contact() {}
	public Contact(String name, String phone, String email) {
		this.name = name; 
		this.email = email;
		this.phone = phone;
	}
	
    	//getter, setter메소드 생략
	
	
	// Contact 객체를 동등성 비교하도록 hashCode()와 equals()를 재정의하기
	// Contact 객체의 name변수가 가지고 있는 값이 서로 같으면 equals() 메소드의 실행결과가 true로 반환되도록 재정의
	@Override
	public int hashCode() {			
		return Objects.hash(name);		    // name이 같으면 같은 해시코드를 갖도록 설정 
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)			    // 전달받은 obj객체와 주소값이 서로 같으면 같은 객체다.
			return true;			    // true 반환
		if (obj == null)			    // 전달받은 obj객체(비교대상)가 null이면
			return false;			    // false 반환(메소드를 실행했는데 null값과 같을 수 없음)
		if (getClass() != obj.getClass())	    // getClass()는 현재 객체의 설계도 정보, obj.getClass()는 비교대상객체의 설계도 정보를 비교해서 
			return false;			    // 서로 다르면 다른 설계도로 만들어진 객체다. (=다른객체) 
		Contact other = (Contact) obj;		    // 위에 해당하지 않으면 같은 설계도로 만들어진 객체이므로, Contact 타입으로 형변환 가능
		return Objects.equals(name, other.name);    // 이 객체의 name과 비교대상 객체의 name을 비교한 값을 반환한다. 
	}

재정의한 equals는 동등성비교 (값 비교)

- 주소값이 같으면 true

- 비교대상이 null이면 false

- 설계도가 다르면 false (같은 설계도로 여러 객체를 만드니까 값이 다 다름)

-> 같은 설계도로 만든 객체니까 상위클래스로 형변환 가능

-> 이 객체의 name과 비교대상의 name이 같은지 비교

 

-ContactApp 

public class ContactApp {

	public static void main(String[] args) {
		Contact c1 = new Contact("김유신", "010-1111-1111", "kim@naver.com");
		Contact c2 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");
		Contact c3 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");
		
		System.out.println("### c1, c2 참조변수가 참조하는 Contact객체가 같은 객체인지 여부를 반환하기");
		System.out.println(c1.equals(c2));	// false
		System.out.println(c2.equals(c1));	// false
		System.out.println(c1.equals(c3));	// false
		System.out.println(c2.equals(c3));	// 재정의 전=false, 재정의 후=true (문자열의 내용은 똑같지만, 주소값이 달라서) 
							// c2와 c2참조변수가 참조하는 객체는 같은 이름을 가지고 있다.

 

-결과

### c1,c2 참조변수가 참조하는 Contact객체의 해시코드 확인하기
44498463
43752720
43752720	//이름이 같으면 해시코드가 같다고 재정의했음

### c1, c2 참조변수가 참조하는 Contact객체가 같은 객체인지 여부를 반환하기
false
false
false
true

 

 

 

 

1-3. Class<?> getClass()

  • 객체의 설계도 정보를 표현하는 Class 객체를 반환
  • Class 객체는 패키지정보, 클래스정보, 멤버변수 정보, 생성자 정보, 메소드 정보를 모두 포함
  • 우리는 잘 사용x, 외부 라이브러리에서 자주 사용
    우리가 객체를 전달할 때, 그 객체 안에 뭐가 있는지 외부 라이브러리에 전달 
  • 재정의  X 

 

-이 메소드 실행은 아직 몰라도 됨

import java.lang.reflect.Field; 

public class ContactApp {

	public static void main(String[] args) {
		Contact c1 = new Contact("김유신", "010-1111-1111", "kim@naver.com");
		Contact c2 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");
		Contact c3 = new Contact("강감찬", "010-2222-2222", "kang@naver.com");
		
		Class<?> clazz = c1.getClass();			// 키워드는 변수명으로 쓸 수 없음 
		Field[] fields = clazz.getDeclaredFields();	// 멤버변수 획득 
		for(Field field : fields) {
			String typeName = field.getType().getName();
			String fieldName = field.getName();
			System.out.println(typeName + ", "+ fieldName);
		}
	}
}

 

java.lang.String, name
java.lang.String, email
java.lang.String, phone

 

=> c1이라는 객체에 변수가 name, email, phone이 있고, 변수들의 타입이 String이라는 것을 알 수 있음 

 

 

 

1-4. wait(), notify()  

  • thread : 프로그램 안에서 실행되는 더 작은 단위의 프로그램
                 스레드가 동시에 너무 여러개가 진행되면 컴퓨터 성능이 느려짐
  • wait( ) : 아직 실행하지 않고 대기상태인 스레드
  • notify( ) : wait 상태의 스레드를 사용하기 위해 깨우는 것

 

 

 

1-5. Object clone()

  • 객체의 복제본 생성하기 

 

Contact src = new Contact("김유신", "010-1111-1111", "kim@naver.com");

src.clone 은 왜 안뜰까? 

 

 

 

접근제한자의 순서

public         - 전체 공개
                    - 같은 패키지, 다른 패키지의 모든 클래스에 공개 

protected   - 같은 패키지 내에서만 공개.
                    - 단, 하위클래스는 다른 패키지여도 공개

private        - 비공개

 

 

- java.lang 패키지 안에 Object 객체가 있음 

- Object객체 안에 

  protected Object clone() { ... } 

  public int hashCode() { .. } 

  public String toString() { ... } 

  public boolean equals(Object obj) { ...} 

 

- day18 패키지에 Object를 상속받아서 Contact라는 객체를 만들었어

 

- day18 패키지에 ObjectApp라는 실행객체를 만들고 그 안에 main메소드, Contact 객체 생성

- 이때,

   c.hashCode();      // c변수가 가리키는 Contact 객체의 hashCode() 메소드 

   c.toString(); 

  은 실행이 돼 ( 왜? hashCode와 toString의 접근제한자가 public(전체공개)이라서 ) 

 

- clone()의 접근제한자는 protected

  Object 클래스는 "java.lang 패키지"      Contact 클래스는 "day18 패키지" 라서

  원래 Object 객체의 protected Object clone() 메소드는 호출을 못해. public(전체공개)만 호출할 수 있어. 

  원래 Contact 객체에서 Object 객체의 clone 메소드를 볼 수 없는데, 

  단, 하위클래스에서는 다른 패키지여도 볼 수 있기 때문에 Object를 상속받은 Contact 객체에서 볼 수 있음 

  

- 근데 직접적으로 호출할 수는 없고, 접근할 수 있는 코드를 따로 만들어야 함 

  copy() 라는 공개된 메소드 안에 clone()을 실행하는 코드를 만들어줌

  이걸 통해 Objecct안에 있는 clone() 메소드 실행

 

- 그래서 ObjectApp 에서 

c.clone()은 안되고 

c.copy()는 됨 (c.copy -> Contact 객체의 copy 메소드 -> Object 객체의 clone메소드) 

 

 

 

-Contact 객체 

public class Contact implements Cloneable { // 이걸 구현하지 않으면 오류

	private String name;
	private String email;
	private String phone;
	
	public Contact() {}
	public Contact(String name, String phone, String email) {
		this.name = name; 
		this.email = email;
		this.phone = phone;
	}
	
   	// getter,setter 메소드 
	
	// Contact객체의 복제본을 반환하는 메소드 
	public Contact copy() throws CloneNotSupportedException {
		Contact contact = (Contact) clone(); //clone의 반환값은 항상 Object -> Contact로 형변환 
		return contact;
	}

 

public class ContactApp2 {

	public static void main(String[] args) throws Exception {
		// 객체의 복제본을 생성하기
		// 이걸 하려면 Cloneable 인터페이스를 먼저 구현해야 함.
		
		// 원본 Contact 객체 
		Contact originContact = new Contact("김유신", "010-1111-1111", "kim@naver.com");
		
		// 복제본 Contact 객체 
		// 복제본 Contact 객체는 원본 Contact 객체는 같은 값을 가지고 있지만, 서로 다른 객체다 (주소값이 다름) 
		Contact copiedContact = originContact.copy();	//copy메소드의 반환값이 Contact 
		
		System.out.println(originContact);
		System.out.println(copiedContact); 
	}
}

 

Contact [name=김유신, email=kim@naver.com, phone=010-1111-1111]
Contact [name=김유신, email=kim@naver.com, phone=010-1111-1111]

 

 

  • Markup Interface : 메소드가 하나도 없는 인터페이스
    • 목적) 객체에 특정한 작업이 가능한지 불가능한지를 표시하는 용도로 사용되는 인터페이스
    • 예)
      java.lang.Cloneable
      이 인터페이스를 구현한 클래스로 생성한 객체만 복제가 가능하다.
      (내가 복제를 허용한 객체만 복제가 가능하도록) 
      java.io.Serializable
      이 인터페이스를 구현한 클래스로 생성한 객체만 입출력이 가능하다.
    • public class Employee extends Person implements Cloneable, Serializable { }
      --> 이 객체는 복제도 가능하고, 입출력도 가능해
    • copy를 하기 전에 이 인터페이스를 구현했는지 확인해야 함 

 

 

 


 

 

 

2. String 클래스 

 

  • 문자열을 표현하는 객체다.
  • 문자열(String)은 불변객체다.
    • 한번 생성된 문자열은 절대로 변하지 않는다. (새로운 객체가 생성되는 것) 
  • String str1 = new String ("SW Expert Academy Work");   // 원래 클래스는 이렇게 객체를 생성해야 하는데
    String str1 = "SW Expert Academy Work";                       // String만 예외적으로 허용

2-1. String 클래스의 주요 메소드 (외워야함) 

  • int length()
    • 문자열의 길이를 반환 (공백 포함)  
System.out.println("### length() 메소드");
String str1 = "SW Expert Academy Work";		// 이 문자열 자체가 객체인 것은 아님. 이 문자열을 포함하고 있어야 함 
// String str1 = new String("SW Expert Academy Work");
int len = str1.length();
System.out.println("문자열의 길이: "+len);

 

### length() 메소드
문자열의 길이: 22

 

 

 

  • boolean isEmpty()
    • 문자열도, 공백도 없는 경우 true 반환
System.out.println("### isEmpty() 메소드");

System.out.println(str1.isEmpty());	// false
System.out.println("  ".isEmpty());	// false (문자가 있다고 봄)
System.out.println("".isEmpty()); 	// true

 

### isEmpty() 메소드
false
false
true

 

 

 

  • boolean isBlank() 
    • 문자열이 없는 경우, 공백인 경우 true 반환 
    • 예를들어, 필수입력값이 비어있으면 안되잖아 -> 이럴 때 사용 
System.out.println("### isBlank() 메소드");

System.out.println(str1.isBlank());	// false
System.out.println("  ".isBlank());	// true (공백도 비어있다고 봄) 
System.out.println("".isBlank());	// true

 

### isBlank() 메소드
false
true
true

 

 

 

  • boolean equals(Object obj),  boolean equalsIgnoreCase(String str) 
    • boolean equals(Object obj)
      문자열의 내용이 일치하면 true를 반환 (대소문자 구분)
    • boolean equalsIgnoreCase(String str)
      문자열의 내용이 일치하면 true를 반환 (대소문자를 구분하지 않음)

    • (※ 개중요) 문자열의 비교에서 상수가 무조건 앞에 와야 함! 

      grade.equals("골드")        //  X
      grade = null값을 넣으면,
      null.equals -> 오류

      "골드".equals(grade)        //  O
      grade = null값을 넣으면,
      "골드".equals(null) -> 오류 x 

ex)

public class StringApp1 {

	public static void main(String[] args) {
    
	// 이 메소드는 grade 가 null값을 인자로 전달받으면 NullPointerException 오류가 발생 (잘못된 예) 
	public static void test1(String grade) {
		if(grade.equals("골드")) {
			System.out.println("골드등급은 5% 적립");
		} else if(grade.equals("실버")) {
			System.out.println("실버등급은 2% 적립");
		} else if(grade.equals("브론즈")) {
			System.out.println("브론즈등급은 1% 적립");
		} else {
			System.out.println("유효한 등급이 아닙니다.");
		}
	}
	
	// 이 메소드는 grade가 null값을 인자로 전달받으면 "유효한 등급이 아닙니다."가 출력된다.
	// 
	public static void test2(String grade) {
		if("골드".equals(grade)) {
			System.out.println("골드등급은 5% 적립");
		} else if("실버".equals(grade)) {
			System.out.println("실버등급은 2% 적립");
		} else if("브론즈".equals(grade)) {
			System.out.println("브론즈등급은 1% 적립");
		} else {
			System.out.println("유효한 등급이 아닙니다.");
		}
	}

 

 

 

System.out.println("### equals(Object obj) 메소드");
		 
System.out.println("abc".equals("abc"));		// true
System.out.println("abc".equals("ABC"));		// false
System.out.println("abc".equalsIgnoreCase("abc"));	// true
System.out.println("abc".equalsIgnoreCase("ABC"));	// true 
		
//StringApp1.test1("골드");
//StringApp1.test1(null);		//nullPointerException 오류 발생
//StringApp1.test2("골드");
//StringApp1.test2(null);

 

### equals(Object obj) 메소드
true
false
true
true

 

 

 

  • boolean contains(CharSequence s)
    • 지정된 문자열이 포함되어 있으면 true 반환
System.out.println("### contains(CharSequence str) 메소드");
        
System.out.println(str1.contains("SW"));	// true
System.out.println(str1.contains("study"));	// false

 

### contains(CharSequence str) 메소드
true
false

 

 

 

  • String substring(int begin)
    • 지정된 위치부터 끝까지의 문자열을 새로 만들어서 반환
  • String substring(int begin, int end)
    • 지정된 시작위치부터 끝위치 앞까지의 문자열을 새로 만들어서 반환
System.out.println("### substring(int begin), substring(int begin, int end) 메소드");

String str2 = "abcdefghijklmnopqrstuvwxyz";
String substr1 = str2.substring(0);		// str2의 0번째부터 끝까지
String substr2 = str2.substring(1);		// str2의 1번째부터 끝까지
String substr3 = str2.substring(2);		// str2의 2번째부터 끝까지
String substr4 = str2.substring(0, 10);		// str2의 0번쨰부터 9번째까지
String substr5 = str2.substring(10, 20);	// str2의 10번째부터 19번째까지 
System.out.println(substr1);				
System.out.println(substr2);				
System.out.println(substr3);
System.out.println(substr4);
System.out.println(substr5);

 

### substring(int begin), substring(int begin, int end) 메소드
abcdefghijklmnopqrstuvwxyz
bcdefghijklmnopqrstuvwxyz
cdefghijklmnopqrstuvwxyz
abcdefghij
klmnopqrst

 

 

 

  • int indexOf(String str)
    • 지정된 문자열이 처음으로 등장하는 위치를 반환. 지정된 문자열이 존재하지 않으면 -1 반환
  • int indexOf(String str, int fromIndex)
    • fromIndex부터 찾아서 등장하는 위치를 반환 
  • int lastIndexOf(String str)
    • 지정된 문자열이 마지막으로 등장하는 위치를 반환
System.out.println("### indexOf(String str), lastIndexOf(String str) 메소드");

String str3 = "My black shirt is real black black shirt!";
System.out.println(str3.indexOf("black"));	// 3
System.out.println(str3.indexOf("black", 10));	// 23
System.out.println(str3.lastIndexOf("black"));	// 29
 
### indexOf(String str), lastIndexOf(String str) 메소드
3
23
29

 

 
 
  • boolean startsWith(String str)
    • 문자열이 지정된 문자열로 시작하면 true를 반환
  • boolean endsWith(String str)
    • 문자열이 지정된 문자열로 끝나면 true를 반환
System.out.println("### startsWith(String str), endsWith(String str) 메소드");

System.out.println("http://www.daum.net".startsWith("http"));	// true
System.out.println("www.daum.net".startsWith("http"));		// false
System.out.println("spring.io".startsWith("http"));		// false
		
System.out.println("보고서.xlsx".endsWith("xlsx"));		// true
System.out.println("보고서.docx".endsWith("xlsx"));		// false
System.out.println("보고서.pptx".endsWith("xlsx"));		// false
System.out.println("보고서.hwpx".endsWith("xlsx"));		// false

 

### startsWith(String str), endsWith(String str) 메소드
true
false
false
true
false
false
false

 

 

 

  • String toUpperCase()
    • 문자열을 대문자로 새로 만들어서 반환
  • String toLowerCase()
    • 문자열을 소문자로 새로 만들어서 반환
  • ※ 기존 문자열을 대문자나 소문자로 변환하는 것이 절대 절대 절대 아니다!!! (문자열의 값이 바뀌는 것이 아님!!)
System.out.println("## toUpperCase(), toLowerCase() 메소드");

String str4 = "The String class represents character strings";
String upperText = str4.toUpperCase();
String lowerText = str4.toLowerCase();
System.out.println(str4);		// str4의 문자열이 변하는 것 X
System.out.println(upperText);		// 대문자 버전의 새로운 문자열 THE STRING CLASS REPRESENTS CHARACTER STRINGS
System.out.println(lowerText);		// 소문자 버전의 새로운 문자열 the string class represents character strings

 

## toUpperCase(), toLowerCase() 메소드
The String class represents character strings
THE STRING CLASS REPRESENTS CHARACTER STRINGS
the string class represents character strings

 

 

 

  • String replace(CharSequenct target, CharSequence replacement)
    • 대상 문자열을 지정된 문자열로 대체한 새로운 문자열을 반환
  • ※ 기존 문자열이 대상 문자열로 변경된 것이 아니다.
System.out.println("### replace(ChartSequence target, ChartSequence replacement) 메소드");

String str5 = "나는 자바가 제일 좋아서 자바를 공부한다.";
String replacedText = str5.replace("자바", "파이썬");
System.out.println(str5);			// str5의 문자열은 변하지 않음!
System.out.println(replacedText);		// 나는 파이썬가 제일 좋아서 파이썬를 공부한다.
 
### replace(ChartSequence target, ChartSequence replacement) 메소드
나는 자바가 제일 좋아서 자바를 공부한다.
나는 파이썬가 제일 좋아서 파이썬를 공부한다.

 

 

 

  • String trim()
    • 문자열의 좌우 불필요한 공백이 제거된 새로운 문자열을 만들어서 반환
  • ※ 기존 문자열의 의미없는 공백을 없애는게 절대 아니다!!
System.out.println("### trim() 메소드");
				
String str6 = "            안녕,            나는          홍길동이야         ";
String trimedText = str6.trim();
System.out.println("["+str6+"]");
System.out.println("["+trimedText+"]");		//단어 사이의 공백은 못지움.

 

### trim() 메소드
[            안녕,            나는          홍길동이야         ]
[안녕,            나는          홍길동이야]

 

 

 

  • String[ ] split(String regex)
    • 문자열을 지정된 구분문자열로 잘라서 각각의 요소를 배열에 담아서 반환
  • 아래의 텍스트에서 "이"씨인 사람들만 출력하기 (텍스트를 분리해야됨 -> split) 
    • text가 참조하는 문자열을 "," 기준으로 잘라서 각각의 이름들을 배열에 순서대로 저장해서 반환 
      names <--- {"이황", "이이", "김유신", "강감찬", "이순신", "류관순", "안중근", "이성계", "이방원"}
String text = "이황,이이,김유신,강감찬,이순신,류관순,안중근,이성계,이방원";
		
String[] names = text.split(",");	// split의 반환타입이 원래 String[]이야 
		
for(String name : names) {
	if(name.startsWith("이")) {
	System.out.println(name);				
	}
}

 

이황
이이
이순신
이성계
이방원

 

 

 

  • static String valueOf(다양한 값)
    • 전달받은 다양한 타입의 값을 문자열로 바꿔서 반환 (정적메소드) 
  • String의 클래스 메소드
    String.valueOf(값) 메소드                   : 지정된 값을 문자열로 변환해서 반환

    String String.valueOf(boolean value)  : true나 false를 "true", "false"로 변환해서 반환
    String String.valueOf(int value)           : 100000을 "100000"로 변환해서 반환
    String String.valueOf(long value) 
    String String.valueOf(double value)
    String String.valueOf(Object value)

  • 왜 문자열로 바꿀까?
    정수의 첫번째 숫자를 출력하고 싶을때 - 1000으로 나누기를 하면 안되는 경우가 있음
    문자열로 바꾸고 0번째부터 1번째 바로 앞까지 (=맨첫번째 숫자)를 쉽게 꺼낼수있음
int number = 1234567890;
String text = String.valueOf(number);
System.out.println(text.substring(0, 1));

 

1

 

 

 

 

 

  • String Builder, String buffer

 

문자열의 이어붙이기 (덧셈기호)

 

String text = "abc" + 10 + true + 3.14 + "가나다라";

문자를 이어붙이고 싶을 때, 덧셈기호(+)로 쓰는 경우 

 

String객체 안에 "abc"가 있는데, 여기서 숫자 10을 더하면

저 String객체가 "abc10"  로 변하는 것이 X !! 문자열이 변하는게 아니라, 새로운 객체가 생김 (문자열은 불변객체이니까!) 

-> 저 String 객체는 그대로 있고, 새로운 String객체에 "abc10"이 새로 생김 

-> 덧셈이 진행될 때마다 새로운 String객체가 생성됨

-> 내가 원하는건 마지막 객체인데, 불필요한 String객체가 많이 생김 -> 메모리 부족 현상 발생

 

 

===> String Builder, String buffer 사용 

 

 

문자열의 이어붙이기 (StringBuilder)

String text = "abc" + 10 + true + 3.14 + "가나다라";

 

StringBuilder builder = new Builder( );    // StringBuilder객체를 만들고 

builder.append("abc");                           // 덧셈기호 대신 append라는 메소드를 사용 

builder.append(10);

builder.append(true);

builder.append(3.14);

builder.append("가나다라");

 

StringBuilder 객체 안에 

내부저장소(버퍼)

append할 때마다, 새로운 객체가 생기는게 아니라 버퍼에 쌓임 

이 버퍼에 쌓인 내용을 문자열로 출력

String text = builder.toString( );   // StringBuilder는 Object의 toString()을 재정의

                                                     (버퍼에 저장된 값을 하나의 문자열로 반환한다.)

 

 

  • StringBuilder, StringBuffer
    • 값을 저장하는 내부 저장소를 가지고 있는 객체
    • 주요 API (특정클래스가 제공하는 기능) 
       * StringBuilder append(String value)    // 얘네는 모두 반환타입이 StringBuilder
       StringBuilder append(int value)
       * StringBuilder append(long value)
       * StringBuilder append(double value)
       * StringBuilder append(boolean value)
       * StringBuilder append(char value)
           - 매개변수의 인자로 전달받은 값을 StringBuilder의 내부 저장소에 순서대로 저장
      String toString()
          - 내부저장소에 저장된 값을 하나의 문자열로 만들어서 반환
          - Object의 toString()메소드를 재정의

 

public class StringApp4 {

	public static void main(String[] args) {
		
		StringBuilder builder = new StringBuilder();
//		StringBuffer buffer = new StringBuffer(); 안써
		
		// StringBuilder 객체의 내부저장소(버퍼)에 값 추가
		builder.append("홍길동");
		builder.append(",");
		builder.append("전자공학과");
		builder.append(",");
		builder.append(3);
		builder.append(",");
		builder.append(180.5);
		builder.append(",");
		builder.append(81.3);
		builder.append(",");
		builder.append('A');
		
		// 내부저장소에 추가된 값을 문자열로 반환
		String text = builder.toString(); //builder는 String이 아닌, StringBuilder타입
		System.out.println(text);
		
		
		// StringBuilder객체의 append()메소드는 StringBuilder객체를 반환하기 때문에 
		// 메소드체이닝(Method Chaining)이 지원되는 메소드
		StringBuilder builder2 = new StringBuilder();
		builder2.append("김유신");	// 이걸 실행하면 StringBuilder가 반환 (append의 반환값이 StringBuilder)
		String text2 = builder2.append("김유신")
			.append(",")
			.append("기계공학과")
			.append(",")
			.append(4)
			.append(",")
			.append(178.6)
			.append(",")
			.append(70.3)
			.append(",")
			.append("AB")		// StringBuiler가 자기자신을 반환(builder도 StringBuilder반환, append도 StringBuilder반환) 
			.toString();		// 바로 문자열로 반환까지 할 수 있음(String text2, .toString()추가) 
		System.out.println(text2);
	}
}

 

홍길동,전자공학과,3,180.5,81.3,A
김유신,기계공학과,4,178.6,70.3,AB

 

 

 

 

 

StringBuilder 

public StringBuilder append(String value) { ... }

애플리케이션 안에

스레드라는 작은 프로그램이 있는데, 서로 독립적으로 존재

append 메소드를 실행하는 스레드

문이 활짝 열린 StringBuilder안으로 

아무 쓰레드가 들어와서 기록 ( 다른 쓰레드가 끼어들어서 같은 칸에 기록할려고도 함 ) 

-> 멀티쓰레드에 안전하지 않음 (Thread - unsafe) 

 

 

StringBuffer 

public synchronized StringBuffer append(String value) { ... }

아무나 끼어들 수 없음 

synchronized 라는 키워드로 인해서 잠글 수 있음 

메소드를 실행하려면 열쇠를 갖고있어야 되는데 열쇠는 한개밖에 없어 

열쇠를 갖지못한 쓰레드는 절대로 메소드를 실행할 수 없음

메소드 실행 후 열쇠 반환 

다음 열쇠를 가진 쓰레드가 다음 칸에서 메소드 실행

절대로 같은 장소에 쓰려는 충돌 x 

-> 멀티쓰레드에 안전함 (Thread - safe)

 

==> 멀티쓰레드 환경이면 버퍼, 멀티쓰레드 환경이 아니면 빌더쓰기 

      (우리는 항상 안전한 방식으로 하기 때문에, 빌더를 쓸거임)

 

 

웹서버에서는 클라이언트(웹브라우저)의 요청을 처리하기 위해서 

많은 스레드를 만들고 동시에 처리함 (멀티스레드) 

멀티스레드가 각각 독립적으로 실행 (서로 영향을 안줌) 

웹브라우저(클라이언트)가 로그인하기의 기능을 요청 

-> 웹서버에서 로그인하기의 기능 실행(로그인하기 메소드 안에 변수가 있음)

-> 스레드가 메소드를 실행 -> 메소드영역의 스택에 로그인하기 메소드가 각각 독립적으로 생김 

-> 메소드영역의 로그인하기 메소드에 각각 변수가 독립적으로 존재, 실행 (영향없음) 

-> 근데 객체에는 멤버변수가 하나밖에 없어 -> 메소드영역에서 메소드를 실행할 때마다 객체의 멤버변수 값을 덮어씀 -> thread unsafe 

-> 그래서 우리는 멀티스레드 환경에서 멤버변수를 읽기,쓰기가 아닌 읽기전용으로 함