- 클래스가 다른 클래스를 포함하는 경우, 내부에 포함된 클래스의 명칭
- 파일 크기의 최소화, 보안, 성능 향상, 이벤트 처리등을 쉽게 처리하기 위해 사용한다.
- 자바 클래스 구조를 더 조직화하고, 소스코드를 구현시 효율을 높일 수 있음
- 내부 클래스가 생성되기 위해 외부 클래스의 객체가 반드시 필요
1. 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.
2. 코드의 복잡성을 줄일 수 있다.
class A { // 외부 클래스
public class B { /**
// 내부 클래스(일반 멤버 변수와 동일한 위치)
// Inner 멤버 클래스 : 클래스 안에서 선언된 클래스
// 클래스 내부에서 멤버 변수 처럼 선언된 클래스를 말한다.
// 멤버 변수와 같이 static과 instance 클래스로 나눌 수 있다.
*/
void func() {
class C { // Inner 로컬 클래스 : 메소드 안에서 선언된 클래스
/**
*메소드 내부에서 지역 변수처럼 선언된 클래스를 말한다.
*클래스 이름에서 알 수 있듯이 메소드 안에서 선언된 클래스의 속성은 메소드
* 밖에서 사용할 수 없다.
}
}
외부클래스명 객체명 = new 외부클래스명();
외부클래스명.내부클래스명 객체명 = 외부클래스객체.new 내부클래스생성자();
public class inner_Test {
public static void main(String[] args) {
Shop2 shop2 = new Shop2();
// Customer2 customer2 = shop2.new Customer2();
// customer2.getProduct();
Shop2.Customer2 customer2 = shop2.hiCustomer();
customer2.getProduct();
}
}
// Alt + Shift + R : 선언부와 사용부 동시에 이름 변경하기
// 여기서 수정하면 전부 바뀜
// InnerClass사용
// ① 외부 클래스
class Shop2 {
int product = 10; // ② 필드 만들기
// ⑥ 외부 클래스에서 void 메소드가 아니라 내부 클래스 이름으로 메소드 만들기
public Customer2 hiCustomer() {
// ⑦ return으로 내부 클래스 객체 생성
return new Customer2();
// 이렇게 하는 이유 : 내부 클래스는 외부에서 만들 수 없는데 내부에서 만들려고 하면 쉽기 때문에 내부에서 내부 클래스를 객체를
// 생성해서 내부 클래스를 사용할 수 있게 해준다.
}
// ③ shop2 class안에 만들어진 내부 클래스
class Customer2 {
// ④ 내부 클래스 안에 만들어진 메소드
void getProduct() {
// product를 상속받은 것처럼 사용할 수 있다.
System.out.println("받은 상품의 개수 : " + product); // ⑤
// 아직 이상태에서는 객체를 생성할 수 없다. 내부 클래스라서 숨겨져 있기 때문에
}
}
}
// 내부 클래스 던지기 1
public abstract class Data {
abstract void doSomething();
}
// 내부 클래스 던지기 2
public class Test {
// Data data를 받아와야지 doSomething이 실행되게 만든 메소드
public void f(Data data) {
// Main에서 이미 재정의가 다 끝난 data가 와서 여기서는
// 오류 없이 data.doSomething이 가능하다.
data.doSomething();
}
}
// 내부 클래스 던지기 3
public class Main {
public static void main(String[] args) {
Test t = new Test();
// Test클래스에서 doSomething메소드를 사용하려면 Data data를 받아서 보내야는데
// Data data = new Data()를 생성하지 않으면 보낼 data가 없다.
// 그래서 Data타입 객체를 만들어주는데 추상 클래스라서 자동적으로 내부 클래스가 열린다.
// 방법 1
Data data = new Data() {
@Override
void doSomething() {
System.out.println("두썸씽");
}
};
// 메소드에 넘기는 data라는 객체는 이미 전부 재정의가 되어있다.
t.f(data);
// 방법 2
// 객체를 바로 생성하며 메소드의 매개변수로 넘길 수 있다.
// Data 타입은 추상클래스이기 때문에 바로 생성하면서
// 익명 클래스로 오버라이딩해서 넘겨준다.
t.f(new Data() {
@Override
void doSomething() {
System.out.println("객체를 생성하며 매개변수로 넘기기");
}
}
}
}
일회용
이다.익명 구현 객체
)만을 위한 클래스프로그램 내에서 한번만 객체로 만드는데 사용되는 클래스를 굳이 정의할 필요가 없기 때문입니다. 그리고 재사용성이 없고, 확장성을 활용하는 것이 유지보수에서 더 불리할 때, 비즈니스 로직이 정말 재각각이며, 재사용성이 전혀없어 매번 클래스를 생성해야하는 비용이 더 많을 때 이런 이유로, Runnable이나 Event Listener 객체를 생성하는데 주로 사용됩니다.
객체 하나만 만들고 사용할 건데 굳이 클래스를 만들어주면 낭비이니 익명클래스를 통해서 사용한다.상속받을 클래스를 만들지 않을 때 즉, 부모 클래스를 만들고 그곳에 있는 메소드를 사용하는데 클래스를 만들지 않고 객체를 생성해서 오버라이딩으로 그 메소드를 사용한다.
Animal bird = new Animal() {
public void fly() {
System.out.println("오리날다");
}
@Override
public void makeSomeNoise() {
System.out.println("끼요욧");
}
};
→ new Animal() { };까지는 생성되는 객체
다. 이 객체를 bird에 넣어주는 것임
→ 익명클래스 영역은 new Animal() 뒤에있는 { };
까지가 영역
이다.
→ 익명 클래스 영역은 앞에 있는 생성자를 상속받고 있다. 즉, new Animal() 생성자
를 상속받는 중 그러므로, 익명클래스는 앞에 있는 생성자의 자식 클래스
라고 볼 수 있다.
→ 이상황에서는 자식 클래스에 있는 fly()메소드를 부모 클래스에 넣고 있으므로 업 캐스팅
이다.
→ 그래서 fly는 자식에서 붙였던 내용이지만 자식에만 있는 메소드므로 잘려나가고
→ 오버라이딩된 makeSomeNoise()만 살아남았다.
→ 보통의 경우 fly를 사용하려면 다운 캐스팅을 해서 사용해야지만 익명 클래스는 클래스 이름이 없어서 다운 캐스팅을 사용할 수 없다. 즉, 익명 클래스에서 메소드를 추가하는 것은 의미가 없다.
→ 새로운 메소드는 이 영역 내부에서만 사용 가능하다. 외부에서는 사용 불가
→ 그 앞에 있는 생성자를 통해 만드는 객체 딱 하나만을 위한 클래스이고 그 때 만들어지는 객체는 익명 클래스 안에서 구현한 메소드 내용을 가지게 된다.
→ 이렇게 만들어지는 객체를 익명 구현 객체
라고 한다.
public abstract class Animal {
String name;
String gender;
int age;
public abstract void makeSomeNoise();
}
// 메인
public class Ground {
public static void main(String[] args) {
// 익명 구현 객체
// new Animal()부터 { };까지는 생성되는 객체다.
// 익명클래스 영역은 {부터 };까지
// 부모 클래스에서 추상 클래스로 만들어주면 자동으로 오버라이드가 생성
// 익명 클래스 영역은 앞에 있는 생성자를 상속받고 있다.
// 즉, 익명 클래스는 앞에 있는 생성자의 자식 클래스라고 볼 수 있다.
// 그 앞에 있는 생성자를 통해 만드는 객체 딱 하나만을 위한 클래스이고
// 그 때 만들어지는 객체는 익명 클래스 안에서 구현한 메소드 내용을 가지게 된다.
// 이렇게 만들어지는 객체를 익명 구현 객체라고 한다.
Animal dog = new Animal() {
@Override
public void makeSomeNoise() {
System.out.println("왈왈!!");
}
};
Animal cat = new Animal() {
@Override
public void makeSomeNoise() {
System.out.println("냐옹!!");
}
};
Animal bird = new Animal() {
// 익명 클래스 안에서 메소드를 만들어서 이 메소드는 Animal이라는 부모 클래스에
// 넣어진다. 즉, 업 캐스팅되는 것이다. 그래서 fly메소드는 잘려나간다.
// 보통의 경우 fly를 사용하려면 다운 캐스팅을 해서 사용해야지만
//익명 클래스는 클래스 이름이 없어서 다운 캐스팅을 사용할 수 없다.
// 즉, 익명 클래스에서 메소드를 추가하는 것은 의미가 없다.
// 새로운 메소드는 이 영역 내부에서만 사용 가능하다.
public void fly() {
System.out.println("오리날다");
}
@Override
public void makeSomeNoise() {
System.out.println("끼요욧");
}
};
// 부모 클래스에 있던 메소드를 익명 클래스에서 오버라이딩해서 사용
dog.makeSomeNoise();
cat.makeSomeNoise();
bird.makeSomeNoise();
}
}
상속
받고 있는 것이다.우리가 만드는 클래스에서는 주소값이 아닌 다른 값으로 활용할 수 있도록
재정의를 해서 사용해야 한다.
public boolean equals(Object obj)
객체 자신과 객체 obj가 같은 객체인지 체크한다. 두 주소값이 같은지 확인하는 메소드 String에 xx.equals()하면 String.class에 있는 equals()로 가져서 재정의 된 equals로 가진다.
equals()메서드는 두 객체의 동일함을 논리적으로 재정의하는 메서드입니다.
동일함은 서로 주소는 다르지만 같은 값을 가지는 객체를 뜻하고 서로 같은 주소를 가지는 물리적 동일함과 다른 의미로 사용됩니다. 정리해보면 equals()는 물리적으로 다른 메모리에 위치한 객체라도논리적으로 동일함
을 구현하기 위해 사용되는 메소드입니다.- override 목적: 물리적으로 다른 메모리에 위치하는 객체여도 논리적으로 동일함을 구현하기 위해
class ItemCode {
String code;
public ItemCode(String code) {
this.code = code;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof ItemCode) {
ItemCode code2 = (ItemCode)obj;
return (this.code == code2.code);
}
return false;
}
@Override
public String toString() {
return "아이템 정식 코드 : " + code;
}
}
public class Object {
public static void main(String[] args) {
ItemCode item = new ItemCode("145023723");
ItemCode item2 = new ItemCode("145023723");
// equals를 오버라이드 하기전에는 false
// 하고 나서는 true
System.out.println(item.equals(item2));
// "145023723"이게 매개변수 code에 넣어져서 toString에서 return "아이템 정식 코드 : " + code이것이 반환해서
// toString을 오버라드해서 아이템 정식 코드 : 145023723 출력
// 오버라이드 하지 않으면 Object에 있는 toString을 가져오지만 오버라이드해서 내가 만든 클래스에 있는 toString을 가져와서
// item에 대한 정보를 알 수 있게 해준다.
System.out.println(item);
}
}
=====================================================================
class Student {
int srudentNum;
String studentName;
public Student(int srudentNum, String studentName) {
this.srudentNum = srudentNum;
this.studentName = studentName;
}
@Override
// String("abc")에서 받아온 abc를 obj에 넣으면서 Object로 업캐스팅하고
public boolean equals(Object obj) {
// 업캐스팅한 abc를 Student로 형변환 가능한것인지 확인 즉, 포함된 것인지 확인
if(obj instanceof Student) {
// true라면 obj(abc)를 Student로 다운캐스팅
Student std = (Student) obj; // Object클래스로 업캐스팅된걸 다운캐스팅
return (this.srudentNum == std.srudentNum);
}
return false;
}
}
public class ObjectClass_Equals {
public static void main(String[] args) {
System.out.println("=============== equals 재정의 전 =================");
String str1 = new String("abc");
String str2 = new String("abc");
// str1==str2 에서 ==은 주소값이 동일한지 물어보는 것임으로 물리적동일함을 묻는 것이고
// 두 인스턴스는 다른 주소에 있기 때문에 false가 반환됩니다.
System.out.println(str1 == str2); // false
// stra.equals(str2)는 논리적 동일성을 묻고 있기 때문에 두인스턴의 값은 abc로 같기에 true가 반환됩니다.
System.out.println(str1.equals(str2)); // true
System.out.println("=============== equals 재정의 후 =================");
Student kim = new Student(100, "김민주");
Student kim2 = kim;
Student minju = new Student(100, "김민주");
// kim과 kim2는 물리적으로 같은 주소를 가지고 있기 때문에 true가 반환됩니다.
System.out.println(kim == kim2); // true
// kim과 minju는 물리적으로 같지 않기 때문에 false가 반환됩니다.
System.out.println(kim == minju); // false
// 메서드에서 사용될 때 비교되는 항목이 자동으로 Object로 업캐스팅 되기 때문에
// instanceof를 사용해서 안전하게 Student 클래스로 다시 다운캐스팅하고
// 두 항목의 studentNum을 비교하게 재정의합니다. true가 반환됩니다.
System.out.println(kim.equals(minju)); // true
}
}
public String toString()
객체 자신의 정보를 문자열로 반환한다. toString의 용도는 일반적으로 내부의 데이터를 문자열로 보기 쉽게 만들어주고 그것을 문자열로 반환한다가 맞긴합니다. 하지만 모든 클래스들이 다 문자열로
변환할 수는 없으므로 모든 클래스들이 모두 toString()을 반드시 오버라이드하여 사용해야 한다가 필수는 아닙니다. 단지, 내부 내용을 테스트하거나 출력해보고 싶거나 혹은 문자열로 출력이 가능하거나 할 경우에만 사용한다.객체 출력시 나올 문자열 정의 / 객체가 가지고 있는 정보들을 설명하는 문자열 - override 목적: 객체의 정보를 문자열 형태로 표현하고자 할 때
class Book {
String title;
String author;
public Book(String title, String author) {
this.title = title;
this.author = author;
}
// object에 있는 ToString을 여기서 재정의를 해준다.
@Override
public String toString() {
return author + ", " + title;
}
}
public class ObjectClass_ToString {
public static void main(String[] args) {
Book book = new Book("토지", "박경리");
// class Book에서 ToString을 재정의를 하지 않았으면 Object에 있는 toString을 가져와서
// hashCode를 가져온다. 그러나 class Book에서 재정의를 해줬기 때문에
// return author + ", " + title ← 이것들이 반환
System.out.println(book); // 출력 : 박경리, 토지
}
}
================================================================
class Car {
String brand;
public Car(String brand) {
super();
this.brand = brand;
}
// 재정의를 해줘서 내가 원하는 대로 뽑아올 수 있게 해준다.
@Override
public String toString() {
return "브랜드 : " + brand;
}
}
public class Object_Test {
public static void main(String[] args) {
Car mycar = new Car("Ferrari");
// 보기에는 mycar만 있어보이지만 출력을 하면 컴퓨터가 자동으로 mycar.toString으로
// 되게 변경한다. 그래서 toString을 재정의를 하지 않으면 Object class에 있는
// toString을 가져와서 hashCode가 반환 된다.
System.out.println(mycar); // 출력 : 브랜드 : Ferrari
}
}
=============================================================
class ObjectText {
int value;
ObjectText(int value) {
this.value = value;
}
// 보통 일반적으로 equals를 오버라이딩하여 기능 재정의를 한다.
@Override
public boolean equals(Object obj) {
// boolean iseq = this.value == ((ObjectText)obj).value;
// return iseq;
// 예상 가능한 오류를 처리한다.
if(obj instanceof ObjectText) {
return this.value == ((ObjectText)obj).value;
} else {
return false;
}
}
@Override
public String toString() {
return this.value + "입니다.";
// return super.toString();
}
}
public class ObjectExam {
public static void main(String[] args) {
String a = new String("10");
String b = new String("10");
// System.out.println(a);
// System.out.println(b);
// System.out.println(a == b); // 주소 비교
System.out.println(a.equals(b)); // 클래스 비교
System.out.println(a.toString());
ObjectText ot1 = new ObjectText(10);
ObjectText ot2 = new ObjectText(10);
System.out.println(ot1 == ot2); // false
System.out.println(ot1.equals(ot2));
}
}
hashCode()
- 해쉬값(주소값 관련된 어던 int값 리턴)
- hashCode 메소드는 객체의 해시코드 값을 리턴한다.
- hash는 hashTable 이라는 배열을 이용해 데이터를 저장하고 주소값을 저장하기 때문에 많은양의 데이터를 저장하고 빠른 검색이 가능하다.
- 각 객체의 hashCode는 유일하며 같은 값을 가질 수 없다.
객체가 변경이 되더라도 hashCode는 변하지 않는다.override 목적: 두 개의 서로 다른 메모리에 위치한 객체가 동일성을 갖기 위해
lass Main {
int number = 1;
}
public class ObjectClass_HashCode_Exam {
public static void main(String[] args) {
Main a = new Main();
Main b = new Main();
System.out.println("객체 변경전 a hashCode값 → " + a.hashCode()); // → 1651191114
System.out.println("객체 변경전 b hashCode값 → " + b.hashCode()); // → 1586600255
b.number = 2;
System.out.println("객체 변경후 b hashCode값 → " +b.hashCode()); // → 1586600255
// b의 객체를 1에서 2로 변경했지만, hashCode는 변경이 되지 않았다.
}
}
====================================================================================
class User {
int userid;
int userpw;
public User(int userid, int userpw) {
this.userid = userid;
this.userpw = userpw;
}
@Override
public boolean equals(Object obj) {
// 1. 타입비교(해당하는 클래스 타입의 객체가 매개변수로 넘어 왔는지)
if(obj instanceof User) {
// 2. 다운캐스팅
User target = (User)obj;
// 3. 조건판별
if(this.userid == target.userid) {
if(this.userpw == target.userpw) {
return true;
}
}
}
return false;
}
// hashCode를 재정의를 안하면 밑에 hashCode가 주소 값을 반환한다.
// 그래서 hshCode를 재정의 해줘서
@Override
public int hashCode() {
return userid;
}
}
public class Object_Test2 {
public static void main(String[] args) {
String msg1 = "RedVelvet";
String msg2 = "RedVelvet";
System.out.println(msg1 == msg2); // true
String msg3 = new String("RedVelvet");
String msg4 = new String("RedVelvet");
System.out.println(msg3 == msg4); // false
System.out.println(msg3.equals(msg4)); // true
// 동위 객체
User user1 = new User(1, 1234);
User user2 = new User(1, 1234);
System.out.println(user1.equals(user2));// false
System.out.println(user1.hashCode()); // 1
System.out.println(user2.hashCode()); // 1
}
}
// String 타입 hashCode 사용하기
public boolean hashCode(Object obj) {
CarDTO anotherobj = (CarDTO)obj;
return (this.carnum.equals(anotherobj.carnum));
}
자바에서 원시 타입의 변수와 같이 가장 많이 사용되는 문자열 변수
하지만 참조 타입의 클래스형 문자열 변수로 자바에서는 편의를 위해 제공한다.
기본적으로 참조 타입의 변수지만 편의를 위해 일부는 원시 타입의 변수처럼 사용가능하다.
ToString 클래스를 만들면 모든 클래스는 Object를 상속하기 때문에
ToString클래스 또한 Object에 메서드를 사용할 수 있습니다.
String str = new String(“안녕하세요”); // 원래는 이게 정석
String str = “안녕하세요”; // 원시타입처럼 사용 가능 개선
하지만 위의 경우 외부적으로 같지만 메모리의 상태는 다르다.
boolean equals(Object obj)
obj 매개변수 문자열과 값을 비교하여 같으면 true를 반환한다.
char charAt(int index)
저장된 위치(index)에 있는 문자를 알려준다.
System.out.println(Test.charAt());
→ 객체 생성은 charAt이 안된다.
int compareTo(String str)
● 매개변수로 받은 문자열(str)과 사전순서로 비교한다.
● 동일하면 0을 앞이면 음수를, 뒤면 양수를 반환한다.
int indexOf(int ch)
● 주어진 문자(ch)가 문자열에 존재하는지 확인하여
● 위치(index)를 반환한다. 못 찾으면 -1을 반환한다.
System.out.println(sen.indexOf("H")); // H가 있는 첫번째 위치 반환(0)
System.out.println(sen.indexOf("i")); // i가 있는 두번째 위치 반환(1)
System.out.println(sen.indexOf("h")); // h가 없어서 -1을 반환
String substring(int begin, int end)
● 주어진 시작위치(begin)부터 끝위치(end) 범위에 포함된 문자열을 반환한다.
● 단 시작위치는 포함되지만 끝 위치는 포함되지 않는다.
int length()
문자열의 길이를 알려준다.
String replace(char old, char new)
문자열 중의 문자(old)를 새로운 문자(new)로 바꾼 문자열로 반환한다.
String replaceAll(String regex, String replacement)
문자열 중에서 지정된 문자열(regex)과 일치하는 것을
새로운 문자열(replacement)로 모두 변경한다.
String toUpperCase()
문자열을 전부 대문자로 교체한다.
String toLowerCase()
문자열을 전부 소문자로 교체한다.
String trim()
문자열 앞뒤에 있는 공백을 제거한다.(단, 중간은 제외)
String[] split(String regex)
regex 구분자를 기준으로 문자열을 앞뒤로 쪼개에 배열로 반환한다.
String join((String delimiter, CharSequence... elements)
문자열 배열을 하나의 문자열로 합쳐 반환한다.
import java.util.Arrays;
public class StringExam {
public static void main(String[] args) {
// 일반적으로 String 클래스 사용시 가장 많이 사용하는 자동 생성 방식
String str1 = "Hello";
String str2 = "Hello";
// 클래스 객체 생성 방식대로 new 연산자를 이용한 객체 생성 방식
String nstr1 = new String("Hello");
String nstr2 = new String("Hello");
// 메모리 주소 비교
System.out.printf("str1 addr : 0x%x\n", System.identityHashCode(str1));
System.out.printf("str2 addr : 0x%x\n", System.identityHashCode(str2));
System.out.printf("nstr1 addr : 0x%x\n", System.identityHashCode(nstr1));
System.out.printf("nstr1 addr : 0x%x\n", System.identityHashCode(nstr2));
System.out.println("=======================================");
// String 객체 변수의 값을 비교하기 위해 equals를 사용한다.
System.out.println(str1.equals(str2)); // 값동일
System.out.println(str1.equals(nstr1)); // 값동일
System.out.println(str1.equals(nstr2)); // 값동일
System.out.println(nstr1.equals(nstr2)); // 값동일
System.out.println("=======================================");
// char charAt(int index) 지정된 위치(index)의 문자를 반환한다.
System.out.println(str1.charAt(1));
System.out.println(str1.charAt(3));
// int compareTo(String str) 매개변수로 받은 문자열(str)과 사전순 비교
// 비교해서 동일하면 0을 반환, 앞으면 음수, 뒤면 양수
System.out.println(str1.compareTo("Hello"));
System.out.println(str1.compareTo("Gello"));
System.out.println(str1.compareTo("Iello"));
System.out.println(str1.compareTo("Hallo"));
System.out.println(str1.compareTo("hallo"));
System.out.println("=======================================");
// int indexOf(int ch) 주어진 문자(ch)가 문자열에 존재하는 확인
// 그리고 위치(index)를 반환한다, 없으면 -1 반환
System.out.println(str1.indexOf("H"));
System.out.println(str1.indexOf("I"));
System.out.println(str1.indexOf("L"));
System.out.println(str1.indexOf("llo"));
System.out.println(str1.lastIndexOf("lo"));
System.out.println("=======================================");
// String substring(int begin)
// 주어진 시작위치(begin)부터 끝까지 문자열을 반환
// String substring(int begin, int end);
// 주어진 begin 부터 끝 end 까지 문자열을 반환
// 단, 끝위치의 문자는 포함되지 않는다.
System.out.println(str1.substring(1));
System.out.println(str1.substring(1,3));
System.out.println(str1.substring(2,3));
System.out.println("=======================================");
// int length() 문자열 길이 반환
System.out.println(str1.length());
// length와 substring 응용
System.out.println(str1.substring(1, str1.length()));
System.out.println(str1.substring(0, str1.length() -1));
System.out.println("=======================================");
// String replace(char old, char new) 문자열 안 문자(old)를 새로운 문자(new)로 바꿈
System.out.println(str1.replace("l", "L"));
System.out.println("=======================================");
// String replaceAll(String regex, String replacement)
// 일치하는 모든 문자열 치환
String text = "Welcom Hello Hello Hello";
System.out.println(text);
System.out.println(text.replaceAll("Hello", "안녕하세요"));
System.out.println("=======================================");
// String toUpperCase()
// 문자열을 전부 대문자로 교체
System.out.println(str1.toUpperCase());
System.out.println("=======================================");
// String toLowerCase()
// 문자열을 전부 소문자로 교체
System.out.println(str1.toLowerCase());
System.out.println("=======================================");
// 대소문자가 마구 섞여 있는 경우 맨 앞글자만 대문자로 만들고 싶다.
String a = "heLlo".toLowerCase();
a.replace("h", "H");
// 위에 두 문장을 하나로 하는 법
System.out.println("heLlo".toLowerCase().replace("h", "H"));
System.out.println("=======================================");
// String trim()
// 문자열 앞뒤에 있는 공백을 제거한다.( 단, 중간은 제외)
System.out.println(" 안녕 하세요 ".trim());
// 모든 공백 제거
System.out.println(" 안녕 하세요 ".replaceAll(" ", ""));
System.out.println("=======================================");
// String[] split(String regex)
// regex 구분자를 기준으로 문자열을 앞뒤로 쪼개어 배열로 반환
String sp = "어머나#땅콩#놀이#반갑다!";
String arr[] = sp.split("#");
System.out.println(Arrays.toString(arr));
// String join(String delimiter, CharSequence... elements)
// 문자열 배열을 하나의 문자열로 합쳐 반환한다.
String jointxt = String.join("#", arr);
System.out.println(jointxt);
System.out.println("=======================================");
String retext = String.join(", ", sp.split("#"));
System.out.println(retext);
System.out.println(sp.replaceAll("#", ", "));
System.out.println("=======================================");
}
}
// 추상 클래스
abstract class Human {
private char type; // 성별
private String name;
private int age;
public Human() {
this.type = 0;
this.name = "";
this.age = 0;
}
public Human(char type, String name, int age) {
this.type = type;
this.name = name;
this.age = age;
}
// 추상 메소드 모든 자식은 일단 무조건 구현해야한다.
public abstract void print();
// getter
public char getType() {
return type;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
// setter
public void setType(char type) {
this.type = type;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
import java.util.Arrays;
public class Student extends Human {
final static String JOB = "학생";
// 멤버 변수
private String className;
private int[] score;
// 생성자
public Student() {
super();
className = "";
score = new int[5];
}
public Student(String className, char type, String name, int age, int[] score) {
super(type, name, age);
this.className = className;
this.score = score;
}
// setter
public void setClassName(String className) {
this.className = className;
}
public void setScore(int index, int score) {
this.score[index] = score;
}
// getter
public String getClassName() {
return this.className;
}
public int getScore(int index) {
return this.score[index];
}
@Override
public void print() {
System.out.println("============ 나의 학생 정보 =============");
System.out.println(className + "입니다.");
System.out.println("이름은 " + this.getName() + "입니다.");
System.out.println("나이는 " + this.getAge() + "입니다.");
// Arrays.toString을 이용하여 배열의 값을 문자열로 표시
System.out.println("점수는 " + Arrays.toString(score) + "점 입니다.");
System.out.println("총점은 " + this.getTotal() + "점입니다.");
System.out.println("평점은 " + this.getAverage() + "점입니다.");
System.out.println("=====================================");
}
// 총점 계산하기 메소드
public int getTotal() {
int total = 0;
for (int i = 0; i < score.length; i++) {
total += score[i];
}
return total;
}
// 평균 계산하기 메소드
public double getAverage() {
return getTotal() / this.score.length;
}
// Object 클래스의 equals() 메소드 오버라이딩(재정의)
@Override
public boolean equals(Object obj) {
// 이와 같이 해도 문제는 없지만 오류에 취약한다.
// return this.value == ((ObjectTest)obj).value;
// 그래서 예상 가능한 오류를 처리한다.
if(obj instanceof Student) {
Student st = (Student)obj;
// equals(Object obj) {
// 에서 매개변수로 받은 obj를 Student st = (Student)obj로 형변환하고
// 자신이 가지고 있는 this.score와 외부에서 받은 Student의 score를 비교하는 코드
boolean a = st.getType() == this.getType();
boolean b = st.getAge() == this.getAge();
boolean c = st.getClassName().equals(this.className);
boolean d = st.getName().equals(this.getName());
boolean e = Arrays.equals(st.score, this.score); // this.score은 Student클래스 9번째 줄에 선언
if( a && b && c && d && e) {
return true;
} else {
return false;
}
} else {
return false;
}
// 좀더 간력하게하는 방법.
// if(obj instanceof Student) {
// Student st = (Student)obj;
//
// boolean a = st.getType() == this.getType();
// boolean b = st.getAge() == this.getAge();
// boolean c = st.getClassName().equals(this.className);
// boolean d = st.getName().equals(this.getName());
// boolean e = Arrays.equals(st.score, this.score);
//
// if( a && b && c && d && e) return true;
// }
//
// return false;
}
// Object 클래스의 toString() 메소드 오버라이딩(재정의)
@Override
public String toString() {
return this.className + " " + this.getName() + " " + this.getAge();
// return super.toString();
}
public Student max(Student st) {
return this.getTotal() > st.getTotal() ? this : st;
}
}
public class Teacher extends Human {
final static String JOB = "선생님";
// 멤버 변수
private String className;
// 생성자
public Teacher() {
super();
this.className = "";
}
public Teacher(String className, char type, String name, int age) {
super(type, name, age);
this.className = className;
}
// setter
public void setClassName(String className) {
this.className = className;
}
// getter
public String getClassName() {
return className;
}
// print 메소드(추상 메소드 오버라이드)
@Override
public void print() {
System.out.println("============ 나의 선생님 정보 =============");
System.out.println(className + "입니다.");
System.out.println("이름은 " + this.getName() + "입니다.");
System.out.println("나이는 " + this.getAge() + "입니다.");
System.out.println("성별은 " + this.getType() + "입니다.");
System.out.println("=====================================");
}
}
//학급 클래스로 선생님 객체와 학생 객체들을 가지고 있는 클래스이다.
public class ClassRoom {
// 멤버 변수
private String className;
private Teacher teacher;
private Student[] students;
// 생성자
ClassRoom() {
className = "";
teacher = new Teacher();
students = new Student[10];
for(int i = 0; i < students.length; i++) {
students[i] = new Student();
}
}
ClassRoom(String className) {
this();
this.className = className;
}
// setter
public void setClassName(String className) {
this.className = className;
this.teacher.setClassName(className);
for(int i = 0; i < students.length; i++ ) {
students[i].setClassName(className);
}
}
public void setStudent(int index, Student student) {
this.students[index] = student;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
// getter
public String getClassName() {
return this.className;
}
public Student getStudent(int index) {
return this.students[index];
}
public Teacher getTeacher() {
return teacher;
}
// print 메소드
public void printClassName() {
System.out.println(className + "입니다.");
}
public void printTeacher() {
this.teacher.print();
}
public void printStudents() {
for(int i = 0; i < students.length; i++) {
System.out.println(i+1 + "번 학생정보.");
students[i].print();
}
}
}
public interface SpecialJob {
public abstract int getJobLevel();
public abstract String getJobName();
public abstract void setJobLevel(int level);
public abstract void setJobName(String jobname);
}
public class Boss extends Teacher implements SpecialJob {
final static String JOB = "교장선생님";
final static String SCHOOL = "코리아IT학교";
private int joblevel;
private String jobname;
private int roomno;
// 기본 생성자를 생성 안해줘도 괜찮다.
public Boss() {
this('남', "", 0);
joblevel = 10;
roomno = 101;
}
public Boss(char type, String name, int age) {
// 교장선생님은 맡은 반이 없다.
// 그래서 className을 학교이름으로 설정
// super로 부모 클래스 Teacher 클래스에서 Teacher(String className, char type, String name, int age);
// 4개의 매개변수를 가지고 있는데 type, name, age는 그대로 넘겨주고 Boss는 교장선생님은 학과라는 개념이 없으니
// className을 가져오지 않고 String인 className과 같은 타입인 SCHOOL을 가져온것(같은 타입이면 상관없음)
super(SCHOOL, type, name, age);
jobname = JOB;
joblevel = 10;
roomno = 101;
}
@Override
public int getJobLevel() {
return joblevel;
}
@Override
public String getJobName() {
return jobname;
}
public int getRoomNo() {
return roomno;
}
public String getSchool() {
return this.getClassName();
}
@Override
public void setJobLevel(int joblevel) {
this.joblevel = joblevel;
}
@Override
public void setJobName(String jobname) {
this.jobname = jobname;
}
public void setRoomNo(int roomno) {
this.roomno = roomno;
}
public void setSchool(String school) {
this.setClassName(school);
}
@Override
public void print() {
System.out.println("============ 나의 직업 정보 =============");
System.out.println( this.getClassName() + "의 " + jobname + "입니다.");
System.out.println("이름은 " + this.getName() + "입니다.");
System.out.println("나이는 " + this.getAge() + "입니다.");
System.out.println("방번호는 " + roomno + "호 입니다.");
System.out.println("직급으로는 " + joblevel + "레벨 입니다.");
System.out.println("=====================================");
}
}
public class Aschool {
public static void main(String[] args) {
// 테스트를 위한 객체 3개를 만들자.
Student st1 = new Student("컴퓨터 공학과", '남', "이순신", 22, new int[]{10, 80, 80, 90, 70});
Student st2 = new Student("컴퓨터 공학과", '남', "이순신", 22, new int[]{10, 80, 80, 90, 70});
Student st3 = new Student("컴퓨터 공학", '남', "홍길동", 12, new int[]{80, 70, 90, 90, 40});
// toString을 오버라이드하여 "학과 이름 나이"를 반환한다.
System.out.println(st1.toString());
System.out.println(st2.toString());
System.out.println(st3); // 자동으로 toString() 호출
System.out.println("======================");
// equals을 오버라이드하여 "학과 성별 나이 이름 점수(개별점수)"를 비교한다.
System.out.println("같은 값으로 비교 = " + st1.equals(st2));
System.out.println("다른 값으로 비교 = " + st1.equals(st3));
System.out.println("======================");
System.out.println(st1.getAverage());
System.out.println(st3.getAverage());
System.out.println("======================");
// 두 학생의 총점(total)을 비교하여 점수가 더 큰 학생의 객체를 반환한다.
Student max = st1.max(st3);
System.out.println(max.toString());
}
}