2022-01-11 [java] 배열 복사/2차원 배열/메소드/객체

GGAE99·2022년 1월 12일
0

진도

목록 보기
4/43

주말과 월요일까지... 일이 있어서 데스크탑을 만지지도 못했다...
공부도 물론 잘 못했다. 그래도 여태 조금씩 공부한 내용을 정리해본다.
시작한지 얼마 안된 블로그를 작심삼일로 끝내기는 싫다. 프로그래밍 공부를 시작하면서 내가 나중에 알아보기 쉽도록 정리하고 싶은 마음이 들어서 시작한 블로그다. 계속 열심히 해보자.

배열 복사

배열을 복사하는 방법은 얕은 복사깊은 복사가 있다.
얕은 복사는 원본 배열의 주솟값을 복사해서 가져오는 것 이다. 그러므로 복사해온 배열을 수정하면, 두 배열 모두 값이 수정된다.
깊은 복사는 원본 배열의 주솟값이 아닌 저장되어있는 값을 가져오는 방법이다. 그래서 복사해온 배열을 수정하더라도, 원본 배열의 값은 변함이 없다. 값만 같은 별개의 배열이라고 생각하면 될 것 같다.

얕은 복사를 하는 방법

얕은 복사는 배열을 생성해 원본 배열의 주솟값을 그대로 넣어주면 된다.

int[] arr1 = {1,2,3,4,5,}; //길이가 5인 배열 생성
int[] arr2 = arr1; //길이가 5인 배열의 주솟값을 복사

위와 같은 방법을 사용하면 얕은 복사를 할 수 있다.

깊은 복사를 하는 방법

깊은 복사를 하는 방법으로는, 직접 값을 넣어주는 방법과, 메소드를 사용하는 방법 2개, 총 3개의 방법을 가지고있다. 물론 다른 방식으로 하려면 더 있을 것 같다고 생각은 들지만, 그건 필자는 잘 모르겠다...

  1. int[] arr1 = {1,2,3,4,5,}; //길이가 5인 배열 생성
    int[] arr2 = new int[5]; //길이가 5인 다른 배열 생성
    for(int i=0 ; i<arr1.length ; i++){ //배열의 길이만큼 반복하는 반복문
    arr1[i] = arr2[i]
    }

위와 같이 for문을 사용하여, 모든 경우의 값을 일일이 대입해 주는 방법이 있다.

  1. int[] arr1 = {1,2,3,4,5,}; //길이가 5인 배열 생성
    int[] arr2 = new int[5]; //길이가 5인 다른 배열 생성
    System.arraycopy(arr1,0,arr2,0,arr1.length);

위의 방법은 arraycopy를 사용한 방법이다. arraycopy를 사용할때는 복사할 값의 범위를 지정해줘야한다. arraycopy메소드의 괄호 안에 집어넣으면 된다. 그 순서는 다음과 같다.

  1. 복사 할 원본 배열 이름
  2. 원본 배열 중 복사를 시작할 인덱스 번호
  3. 새 데이터가 들어가 배열 이름
  4. 복사된 데이터가 들어갈 시작 인덱스 번호
  5. 총 복사 할 배열 길이 길이

arraycopy를 사용하면 원본 배열에서 원하는 범위만큼 값을 복사할 수 있기때문에, 특정한 값이 필요할 때 많이 사용한다고한다.

System.arraycopy(arr1,0,arr2,2,3);

위의 코드를 사용했을 경우에 arr2의 내부 값은
arr2[] = {0,0,1,2,3}이 된다. arr1의 1~3번째 값을 arr2의 3~5번째 값으로 넣어준 것 이다.

  1. int [] arr1 = {1,2,3,4,5}; //길이가 5인 배열 생성
    int [] arr2 = new int[5]; //길이가 5인 다른 배열 생성
    arr2 = arr1.clone();

이게 가장 쉬운 방법인 것 같다. 범위를 지정해주는 arraycopy와는 결이 다른 방법이지만, 모든 값을 복사해주려고 할 때, 사용하면 편리할 것 같다.

2차원 배열

2차원 배열은 배열을 한층 더 만든 행과 열을 가진 배열이다. 같은 크기의 배열을 다시 한번 배열로 묶었다고 생각하면 편할 것 같다. 사실 2차원 배열의 행에는 배열의 형태의 값이 들어있는게 아닌, 속해있는 배열의 주솟값이 들어있다. 주솟값을 읽고 그 위치로 가서, 원래 생성되어있던 배열을 읽는 것 이다. 배열도 그렇지만 2차원 배열또한 참조형이다.

arr1[][] ---->0X1234---->{"a","b","c","d"}
l------------>0X1235---->{"c","d","g","r"}.....

위와 같은 형태로 구성된다.

2차원 배열 선언 시 마지막 열 크기를 지정하지 않고, 추 후 각기 다른 길이의 배열을 생성하는 유동적인 형태의 배열도 있는데, 이를 가변배열이라고 한다.

int[][] arr = new int[3][];
arr[0] = new int[3];
arr[1] = new int[2];
arr[2] = new int[4];

위와 같이 다른 길이의 배열을 한 배열에 저장할 수 있다.
2차원 배열은 이거 말고는 딱히 쓸 말이 없는 것 같다..!

메소드

메소드라는 것은 다른 언어의 함수와 같은 기능을 하는 친구이다. 메소드를 호출하게 되면, 전달값을 받고, 내부에 작성된 연산을 진행한 후 결과값을 내보내준다.
메소드의 형태는

[접근제어지시자] 반환형 메소드명 (매개변수){
실행코드;
}
ex)
public void printVelog(){
System.out.println("공부한거 정리해");
}

와 같은 형태이다. 위 printVelog라는 메소드는 공부한것을 정리하라고 말해준다.

메소드의 접근제어지시자는, public, protected, default, private가 있다.
public의 범위가 가장 넓고, private가 가장 좁은 범위를 가지고있다.
public을 사용할 경우, 프로젝트 전체가 이 값에 접근할 수 있고,
protected는 후손 클래스까지,
default는 같은 패키지까지,
private는 해당 클래스 내부까지만 접근이 가능하다.

메소드의 반환형은 void, 기본자료형, 참조자료형, 배열이 있다.
void는 반환 값이 없을 경우를 나타낸다. void외의 다른 반환형을 가진 메소드는 모두 정해진 형태의 return값을 돌려줘야한다.

메소드의 매개변수는 메소드 안에서 전달 받아서 사용하는 값을 넣어주는 것 이다. 메소드의 특성을 나타내준다.
public void method(int num, String str){}과 같은 형태로 사용한다.
저 굵은 부분이 이 메소드를 사용할때 입력받아야 하는 매개변수이다.

public void method(int num, String str){
System.out.println("입력한 숫자는 "+num+"입니다.)
System.out.println("입력한 문자열은 "+str+"입니다.)
}

와 같은 식의 메소드를 만들면, 이 메소드를 사용하기 위해 메소드를 호출하면서 동시에 int값을 가진 변수와 String값을 가진 변수를 같이 생성해주어야 사용할 수 있다. 그 변수는 메소드의 식에 들어간다.

메소드의 오버로딩

우리가 어떠한 변수나 메소드를 선언할 때, 이름을 같게하면 안된다. 그 이유는 이름이 같은 두 변수나 메소드가 있다면, 그것을 호출할때 컴퓨터가 2개중에 무엇을 불러와야할지 모르기 때문이다. 그러나 매개변수의 개수, 형태 두 메소드가 구분이 가능하다면, 같은 이름을 사용할 수 있다. 이것이 메소드의 오버로딩이다.

int num;
int num;
public void method(){}
public void method(){}

이렇게 같은 이름의 변수나 메소드는 호출할 수 없다. 그러나

public void method(){}
public void method(int num, String str){}

위와 같이 매개변수로 두 메소드가 다르다는것을 알 수 있다면, method라는 메소드의 이름이 중복되어도 컴퓨터에서 받아들이고 사용할 수 있다.

public void method(int str, String num){}
public void method(int num, String str){}

이렇게 매개변수의 안에 들어가는 변수의 이름을 같게한다고 해도 이것은 사용하지 못한다. 저 변수는 임의로 선언한 것 뿐, 어떤 변수도 들어갈 수 있기 때문에, 컴퓨터는 위의 메소드를 구분하지 못한다.

public void method(int num, String str){}
public int method(int num, String str){
return 1;
}

리턴값을 바꿔주는 것으로도, 컴퓨터는 두 메소드를 구분하지 못한다.
중요한것은 매개변수이다. 컴퓨터는 매개변수의 형태와, 갯수를 보고 메소드를 구분한다.

ublic void method(String str, int num){}
public void method(int num, String str){}

위와 같이 들어오는 매개변수의 순서를 바꿔주는 형태는 오버로딩의 조건에 성립한다.

객체

올것이 왔다. 우리 타이커스 형님도 못참으신다.
필자는 원래 c언어를 독학하고있었다. 게임 개발자가 하고싶어서 c언어를 하고, c++을 하고, unity를 만지면서, 고등학교 친구들과 게임을 만들었다. 물론 나는 프로그래밍을 할줄도 모르기때문에, 디자인과 전공을 살려서 게임 그래픽을 디자인했다. 물론 엄첨 못한다. 다 그냥 겉만 핥아본거고, 실제로 하라그러면 하지도 못한다. 이게 현실이다. 한참 c언어를 공부하고 있을때 같이 게임을 만들었던 친구가 그거 힘들다고 그만하라고했다. c언어부터 하면 쉽지않다고, 공부가 재미없어질거라고 말해줬다. 객체지향 언어인 c++부터 공부하라고 알려줬다. 이때는 객체지향 언어가 아예 뭔지도 몰랐다. 그리고 객체라는 개념을 접하니, c보다 편리하게 만들었구나 하고 생각했다. 잡설은 여기까지만 말하고..

현재 프로그래밍 언어는 대부분 객체지향언어라고 알고있다. 객체지향 언어라는 것은 클래스와 메소드로 나누어 필요할때, 그것을 불러와 사용하는 것 이라고 생각하면 편할 것 같다.
예를들어, 절차지향프로그래밍은 한 프로그램을 만들때 필요한것을 쭈우우욱 써내려가며 그때그때 코드를 직접 쓰면서 짠다고 하면, 객체지향프로그래밍은 필요한 메소드,함수 등을 미리 만들어 뒀다가 필요할때마다 가서 보고 사용한다고 생각하면된다. 물론 내가 보고 따라쓰는게 아니라, 위치만 알려주고, 컴퓨터가 그쪽으로 가서 자료를 보는 것 이다.
또 클래스를 객체화하면, 클래스의 속성을 가지고있는 다른 객체들도 생성할 수 있다.

객체라는 것은 즉 사전적 의미로는 실체 하는 모든 사물이고, 객체지향 언어에서 객체의 개념은 new 연산자를 통해 클래스의 설계대로 데이터를 메모리에 할당한 결과물이라고 볼 수 있다.

진짜 뭐라고 설명해야할지 모르겠다. 열심히 정리하면서 나도 이해해봐야겠다...

클래스를 사물이 가져야할 부품과 기능이 명시되어있는 설계도라고 하면,
객체는 그 설계도를 통해 만든 실제 사물이라고 생각하면... 꽤 이해가 될 것 이라고 생각한다.
클래스라는 설계도를 보고 객체를 하나하나 만드는 것 이다.
오늘은 여기까지만 정리하겠다...
프로그래밍 초보는 여기까지 정리하는 것도 너무 힘들다... 다른 분들한테는 별거 아니겠지만, 필자한테 있어서는 좀 더 이해하려고 노력해야하는 부분이다. 다음에 더 정리해보겠다.

0개의 댓글