티스토리 뷰

개인공부/JAVA

배열, 기본클래스

날따라해봐요요롷게 2021. 5. 5. 19:50

배열

- 배열이란

- 다차원 배열

- ArrayList 클래스 사용

- 배열 응용

 

기본클래스

- Object 클래스

- String 클래스

- Wrapper 클래스

- Class 클래스

 

#배열이란

: 자료를 순차적으로 관리하는 구조

 

- 배열 선언 , 초기화

 : 자바에서는 어떠한 객체를 사용하기 위해서는 선언과 초기화를 해야한다.

자료형[] 배열이름 = new 자료형[크기];

자료형 배열이름[] = new 자료형[크기];

String[] arr = new String[크기];
int arr1[] = new int[크기];

 

- 배열 초기화

 : 배열은 선언과 동시에 각 요소의 값이 초기화 된다 => 정수(0), 실수(0.0), 객체 배열(null)

 배열 선언과 동시에 특정 값으로 초기화하기

int[] arr = new int[] {1,2,3}; //개수 생략가능
int[] arr = new int[3] {1,2,3}; // ERROR!!!
int[] arr = {1,2,3}; //선언과 동시에 초기화 => new int[크기] 생략 가능!!
// 배열의 자료형을 먼저 선언 후 초기화 하는 과정
int[] arr;
arr = new int[] {1,2,3};

##객체 배열

 : 참조 자료형으로 선언하는 객체 배열 (참조 자료형 변수란 클래스형으로 선언하는 변수)

 

객체배열과 일반 배열의 차이는 선언과 생성을 하면 객체 배열은 배열의 값에 해당 변수의 자료를 저장하는 것이 아닌 객체배열의 요소로 생성된 인스턴스 주소를 값으로 갖는다.

public class ObejctArray1 {
	String name;
	int number;
	
	public ObejctArray1() {
	}
	public ObejctArray1(String name, int number) {
		this.name = name;
		this.number = number;
	}
}
public class ObjectArray2 {

	public static void main(String[] args) {
		ObejctArray1[] arr1 = new ObejctArray1[5]; // 객체배열 생성
		// 해당 객체 배열은 현재 모두 null 값으로 초기화 되어있다.
		// 객체 배열을 선언,생성 하면 인스턴스 5개가 바로 생성되는 것이 아니다.
		// 각각의 배열의 공간에는 인스턴스 주소를 가리키는 주소값이 들어가야 하는데 아직 변수의 공간에 어떤 값도 저장되어 있지 않아 null 값을 갖는다.
		
		arr1[0] = new ObejctArray1("이름1", 1);
		arr1[1] = new ObejctArray1("이름2", 2);
		arr1[2] = new ObejctArray1("이름3", 3);
		
		for(int i=0; i<arr1.length; i++) {
			System.out.println(arr1[i]);
			// 출력된 값은 객체 배열에 저장된 공간의 인스턴스 주소값을 갖고 있다.
		}
	}
}
///// 출력
Array.ObejctArray1@15db9742
Array.ObejctArray1@6d06d69c
Array.ObejctArray1@7852e922
null
null

 

##배열 API

- 배열 복사 : System.arraycopy(src, srcPos, dest, destPos, length)

src = 복사할 배열 이름

srcPos = 복사할 배열의 첫 번째 위치

dest = 복사해서 붙여 넣을 대상 배열 이름

destPos = 복사해서 대상 배열에 붙여 넣기를 시작할 첫 번째 위치

length = src에서 dest로 자료를 복사할 요소 개수

 

public class ArrayCopy {
	public static void main(String[] args) {
		
		int array[] = {1,2,3,4,5};
		int array1[] = {11,22,33,44,55};
		
		System.arraycopy(array, 1, array1, 3, 2);
		for(int i=0; i<array1.length; i++) {
			System.out.println(array1[i]);
		}
	}
}
/////////// 출력
11
22
33
2
3

-객체 배열 복사(얕은 복사)

public class ObjectArray2 {

	public static void main(String[] args) {
		ObejctArray1[] arr1 = new ObejctArray1[5]; // 객체배열 생성
		// 해당 객체 배열은 현재 모두 null 값으로 초기화 되어있다.
		// 객체 배열을 선언,생성 하면 인스턴스 5개가 바로 생성되는 것이 아니다.
		// 각각의 배열의 공간에는 인스턴스 주소를 가리키는 주소값이 들어가야 하는데 아직 변수의 공간에 어떤 값도 저장되어 있지 않아 null 값을 갖는다.
		
		arr1[0] = new ObejctArray1("이름1", 1);
		arr1[1] = new ObejctArray1("이름2", 2);
		arr1[2] = new ObejctArray1("이름3", 3);
		
		ObejctArray1[] arr2 = new ObejctArray1[5];
		System.arraycopy(arr1, 0, arr2, 2, 3);
		
        	arr1[0].setName("1름이");
		arr1[0].setNumber(101);
        
		for(int i=0; i<arr1.length; i++) {
			System.out.println(arr2[i]);
			// 출력된 값은 객체 배열에 저장된 공간의 인스턴스 주소값을 갖고 있다.
		}
	}
}
/////////출력
null
null
Array.ObejctArray1@15db9742
Array.ObejctArray1@6d06d69c
Array.ObejctArray1@7852e922

객체 배열을 복사하면 인스턴스 주소 값을 복사해준다.

위의 코드 arr1[0].setName 을 호출하여 값을 바꾸었다.

arr2는 어떤 값을 출력할까? ===> arr2는 arr1이 setName 메소드를 호출하여 바꾼 값을 보여준다.

그 이유는 객체 배열의 복사는 인스턴스를 주소를 복사하기 때문이다.!!

 

그렇다면, 인스턴스 따로 관리를 하고 싶다면 어떻게 해야 할까?

 

- 깊은 복사

        // arr2 객체 배열의 인스턴스를 따로 생성
		arr2[0] = new ObejctArray1();
		arr2[1] = new ObejctArray1();
		arr2[2] = new ObejctArray1();
		
        //배열 복사 api가 아닌 for문을 이용하여 새롭게 생성된 인스턴스에 값을 복사한다.
        for(int i=0; i<arr1.length; i++){
         arr2[i].setName(arr1[i].getName());
         arr2[i].setNumber(arr1[i].getNumber());
        }        
        
		arr1[0].setName("1름이");
		arr1[0].setNumber(101);
		

피복사 배열의 인스턴스를 따로 생성하여, 각각의 값을 set() 메소드를 이용하여 값을 복사한다.

 

## 향상된 for문과 배열

: 향상된 for문은 배열의 처음에서 끝까지 모든 요소를 참조할 때 사용할 수 있다.

for(자료형 변수 : 배열) {
	반복 실행문;
}

배열의 요소 값을 순서대로 변수에 대입하여 출력하는 것을 반복한다.

public class EhancedForLoop {
	public static void main(String[] args) {
		String[] arr = {"JAVA", "PYTHON", "JAVASCRIPT", "C++", "C#"};
		
		for(String lang : arr) {
			System.out.println(lang);
		}
	}
}
//////////////////출력
JAVA
PYTHON
JAVASCRIPT
C++
C#

 

#다차원배열

: 다차원 배열은 2,3.. 차원 배열을 말한다.

 

일차원 배열과 다른 차이점을 이야기해보자

public class TwoDimension {

	public static void main(String[] args) {
		int arr1[] = {1,2,3,4,5,6};
		int arr2[][] = {{1,2,3},{4,5,6,7,8}};
		
		System.out.println(arr1.length);
		System.out.println(arr2.length);
		System.out.println(arr2[0].length);
		System.out.println(arr2[1].length);
	}
}
/////////////////////////// 출력
6
2
3
5

이차원 배열 arr2의 length는 "2" 로 출력되는 것을 볼 수 있다. ==> 배열의 행의 길이를 출력한다.

arr2[i].length 는 각 행의 열의 길이를 출력한다.

 

#ArrayList 클래스

 : 위에서 익힌 기존 배열은 배열의 길이를 정하고 시작한다.

하지만, 중간에 배열의 길이가 바뀌는 경우에는 취약한 단점을 갖고있다.

이러한 단점을 보완하기 위해 ArrayList 클래스를 사용한다. 

ArrayList는 객체 배열을 관리할 수 있는 멤버 변수와 메서드를 제공하여 배열을 보다 기능성있게 사용할 수 있도록 한다.

메서드 설명
boolean add(E e) 요소 하나를 배열에 추가한다. E는 자료형 의미
int size() 배열에 추가된 요소 전체 개수를 반환
E get(int index) 배열의 index 위치에 있는 요소 값을 반환
E remove(int index) 배열의 index 위치에 있는 요소 값을 제거하고, 값을 반환
boolean isEmpty() 배열이 비어 있는지 확인

 

- ArrayList 클래스 활용

ArrayList<E> 배열이름 = new ArrayList<E>(); // E 는 자료형
ArrayList<String> arr = new Arraylist<String>();

ArrayList 클래스는 java.util 패키지에 구현되어 있는 클래스이다. 즉, 사용하기 위해서는 import 하여 사용해야 한다.

(java.util 패키지는 자료 구조와 알고리즘에 관련된 클래스가 구현되어 있다.)

 

ArrayList 클래스를 사용해보자

import java.util.ArrayList;

public class ArrayList1 {
	public static void main(String[] args) {
		ArrayList<ObejctArray1> arrList = new ArrayList<ObejctArray1>();
		
		arrList.add(new ObejctArray1("이름1", 1));
		arrList.add(new ObejctArray1("이름2", 2));
		
		for(ObejctArray1 list : arrList) {
			System.out.println(list);
			System.out.println(list.getName() + "  " + list.getNumber());
		}
	}
}
////////////////출력
Array.ObejctArray1@15db9742
이름1  1
Array.ObejctArray1@6d06d69c
이름2  2

ArrayList를 자료형으로 ObjectArray1 로 선언하여 생성한다.

ArrayList 객체변수인 arrList는 객체배열을 생성한다. 즉, 인스턴스의 주소값을 갖는다는 것을 잊지말자!!

인스턴스의 주소값을 갖는다는 것은 변수처럼 사용할 수 없다는 것이다.

ArrayList의 add() 메소드를 활용하여 객체를 생성한다. ==> 객체배열에 각각의 인스턴스 생성

향상된 for문을 이용하여 해당 값을 출력한다.

 

#기본클래스

 : javv.lang 패키지에는 많은 클래스들이 포함되어있다. 원하는 클래스를 사용하기 위해서는 import 문을 사용하여 클래스를 선언해야 한다. 

 

## Object 클래스 : 자바 최상위 클래스

자바는 객체 지향 프로그램으로 extends와 implments 등이 빈번하게 일어나며 이를 활용하여 코드를 구현한다.

따라서 각각의 클래스들의 상속관계 즉, 상하위 관계를 정확하게 알아야한다.

 

우리는 클래스를 선언할 때 extends Object를 따로 작성하지 않는다. 그 이유는 자바 컴파일 과정에서 JVM이 해당 코드를 넣어서 컴파일 실행해주기 때문이다.

그렇다면 생각해보자. 모든 클래스가 Object 클래스를 상속받는 다면 Object 클래스의 메소드를 사용할 수 있다는 말이다. Object 클래스의 메소드를 사용하기 위해 해당 메소드들을 알아보자

메서드 설명
String toString() 객체를 문자열로 표현하여 반환. 재정의 하여 설명, 변수 값을 반환
boolean equals(Object obj) 두 인스턴스가 동일한지 판단.
int hashCode() 객체의 해시 코드 값을 반환
Object clone() 객체를 복제하여 새로운 인스턴스를 생성
Class getClass() 객체의 Class 클래스를 반환
void finalize() 인스턴스가 힙 메모리에서 제거될 때 GC에 의해 호출되는 메서드
void wait() 멀티스레드 프로그램에서 사용하는 메소드
void notify() wait() 메소드에 의해 기다리고 있는 스레드를 실행 가능한 상태로 가져옴

위의 메소드들은 재정의하여 사용될 수도 있고 안될 수도 있다. JavaDoc에 들어가 메소드가 final 예약어로 선언된 메서드는 JVM과 관련되어 있기 때문에 재정의가 안된다.

 

- toString()

 : 해당 메소드는 객체 정보를 문자열로 바꾸어 반환한다. 모든 클래스에서는 toString() 메소드를 재정의하여 사용할 수 있다.

public class Ex_toString {
	int number;
	String name;
	
	public Ex_toString(int number, String name) {
		this.name = name;
		this.number = number;
	}

	public static void main(String[] args) {
		Ex_toString method = new Ex_toString(1, "이름");
		System.out.println(method);
		System.out.println(method.toString()); //Object 클래스의 toString 메소드 사용
		
		String str = new String("갑니다~"); //String 클래스 객체 선언,생성
		Integer num1 = new Integer(111); // Integer 클래스 객체 선언,생성
		System.out.println(str); 
		System.out.println(num1);
	}
}
////////////////////////////출력
Array.Ex_toString@15db9742
Array.Ex_toString@15db9742
갑니다~
111

toString() 메소드의 반환값은 생성된 인스턴스의 클래스 이름과 주소 값을 반환한다.

생성한 클래스(Ex_toString)의 인스턴스를 생성하여 그 참조 변수를 반환한다.

즉, 일반적으로 객체를 생성하여 참조변수를 출력하면 위와 같이 클래스 이름과 주소를 반환한다.

참조변수.toString 메소드의 toString() 메소드는 Object 클래스의 메소드를 호출한 것이다.

그와 달리 String, Integer 클래스로 선언하여 참조변수를 출력하면 ==> 클래스이름, 주소값 을 반환하지 않는다.

String, Integer 클래스는 toString() 메소드를 재정의 하였기 때문에 재정의된 반환값을 반환한다. 그 값이 생성하며 넣은 값을 반환하여 출력한다.

 

- equals()

 : equals() 메소드는 원래 두 인스턴스의 주소 값을 비교하여 boolean 값을 반환해 준다.

그런데 서로 다른 주소 값을 가질 때도 같은 인스턴스라고 정의하는 경우가 있다.

이를 구분하기 위해 물리적 동일성, 논리적 동일성으로 나눈다.

물리적 동일성 : 인스턴스의 메모리 주소가 같음

논리적 동일성 : 주소는 다르지만 인스턴스 값이 같음

 

물리적 동일성

Book book1 = new Book();
Book book2 = book1; // 인스턴스 주소 복사

참조 변수가 2개 있을 때 인스턴스가 물리적으로 같다 => 두 인스턴스의 주소 값이 같은것을 가리킨다.

 

물리적 동일성

논리적 동일성

Book book1 = new Book("꿈");
Book book2 = book1; // 인스턴스 주소 복사
Book book3 = new Book("꿈");

 book1, book2 와 book3 가 가리키는 인스턴스는 서로 다른 주소를 갖는다.

하지만 저장된 value가 같다. 이런 경우를 논리적으로 같다 라고 한다.

논리적 동일성

## 동일성, 동등성 비교    (참조 : jisooo.tistory.com/)

- 동일성 비교는 == 와 같다. : 객체의 인스턴스 주소 값을 비교한다. 

     - primitive data type 은 == 를 이용하여 value 비교가 가능하다.

- 동등성 비교는 equals() 메소드를 사용하여 객체 내부의 value를 비교한다.

(primitive data type 이 == 를 사용하여 값 비교가 가능한 이유

==> 변수 선언부는 Java Runtime Data Area의 Stack 영역에 저장이 되고, 해당 변수에 저장된 상수는 Runtime Constant Pool에 저장되어있다. Stack의 변수 선언부는 당 Runtime Contant Pool의 주소값을 가지게 되고, 만약 다른 변수도 같은 상수를 저장하고 있다면, 이 다른 변수도 같은 Runtime Contant Pool의 주소값을 가지게 때문에 엄밀히 말하면 primitive type 역시 주소값 비교가 되는 것이다.)

 

- String 과 Integer 클래스의 equals() 메소드

: String, Integer 클래스의 equals 메소드는 재정의가 되어 해당 물리적 동일성이 아닌 논리적 동일성을 체크하여 비교한다. 즉, 인스턴스 주소 값이 아닌 해당 객체의 value를 비교한다.

public class EqualsMethod {

	public static void main(String[] args) {
		String str1 = new String("AAA");
		String str2 = new String("AAA");
		
		System.out.println(str1 == str2); // 인스턴스 주소 값 비교
		System.out.println(str1.equals(str2)); // 인스턴스의 문자열 value 비교
		
		Integer num1 = new Integer(1);
		Integer num2 = new Integer(1);
		
		System.out.println(num1 == num2);
		System.out.println(num1.equals(num2));
	}
}
///////////// 출력
false
true
false
true

- hashCode()

: hash는 정보를 저장하거나 검색할 때 사용하는 자료 구조이다. 해시 함수의 객체의 특정 정보를 매개변수 값으로 넣으면 그 객체가 저정되어야 할 위치나 저장된 해시 테이블 주소(위치)를 반환한다. 따라서 객체 정보를 알면 해당 객체의 위치를 알 수 있다.

index(저장위치) = hash(key(객체 정보))

hashCode = hash(key); ==> 객체의 해시 코드 값(메모리 위치 값) 반환됨

Object클래스의 toString() 메소드는 참조 변수를 출력할 때 반환된 "해쉬코드값" 을 출력한다. 이 값은 JVM의 heap 메모리에 저장한 "인스턴스 주소 값"이다. 즉, 두 인스턴스가 같다면 hashCode() 메서드에서 반환하는 값이 같다.

따라서 논리적으로 같은 두 객체도 같은 해시코드 값을 반환하도록 hashCode() 를 @override 해주었다면 equals() 메소드 또한 @override 해주어야 한다.

 

public class HashMethod {

	public static void main(String[] args) {
		String str1 = new String("AAA");
		String str2 = new String("AAA");
		
		System.out.println(str1.hashCode());
		System.out.println(str2.hashCode());
		
		Integer num1 = new Integer(1);
		Integer num2 = new Integer(1);
		
		System.out.println(num1.hashCode());
		System.out.println(num2.hashCode());
	}
}
/////////////////////출력
64545
64545
1
1

String, Integer 클래스의 equals()는 재정의 되어있다. ==> hashCode() 또한 함께 재정의 되어있다.

 

(참조 : Do it! 자바 프로그래밍 입문 (저 : 박은종) )

'개인공부 > JAVA' 카테고리의 다른 글

Thread - Sync  (0) 2021.09.10
Exception  (0) 2021.09.09
JAVA - Inner Class, Lambda , Stream  (0) 2021.03.21
JAVA - CLASS  (0) 2021.03.16
JAVA - INTERFACE  (0) 2021.03.12
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함