Java 정리 13
29 Nov 2018
Reading time ~6 minutes
Java 정리 13 - Array, 상속
3차원배열
- 면,행,열로 구성된 배열
// 면의 수
배열명.length
// 행의수
배열명[면의번호].length
// 열의 수
배열명[면의번호][행의번호].length
// 1.선언)
데이터형[][][] 배열명 = null;
// 2.생성)
배열명 = new 데이터형[][][]
// 생성과 선언
데이터형[][][] 배열명 = new 데이터형[면의수][행의수][열의수];
// 3.값할당)
배열명[면의변호][행의번호][열의번호] = 값;
// 4.값사용
배열명[면의번호][행의번호][열의번호]
// 모든 방의 값 출력(일괄처리) - 인덱스 3개 필요
for(int i=0; i<배열명.length; i++) { // 면
for(int j=0; i<배열명[i].length; j++) { // 행
for(int k=0; k<배열명[i][j].length; k++) { // 열
System.out.print(배열명[i][j][k]+" ");
}
System.out.println();
}
System.out.println(); // 다음면으로
}
// 3차원 배열의 한 면은 2차원 배열로 이루어져 있다.
for(면을저장할2차원배열 : 3차원배열명) {
for(행을저장할일차원배열 : 2차원배열) {
for(값을저장할데이터형 : 일차원배열) {
System.out.print(값을저장할데이터형);
}
System.out.println();
}
System.out.println();
}
// 기본형 형식의 사용 - 면 구분괄호, 행 구분괄호 사용
데이터형[][][] 배열명 = { { {값,..}, {값,..}, {..} }, { .. }, ... };
// 3차원 배열의 한면은 2차원 배열로 이루어져있다.
// 2차원 배열의 한행은 1차원 배열로 이루어져있다.
public class Use3DArray {
public Use3DArray() {
int[][][] threeDArr = new int[][][]{
{
{1, 2, 3},
{4, 5, 6}
},
{
{7,8,9},
{10,11,12}
}
};
System.out.println("threeDArr의 면의수 : "+threeDArr.length
+", 행의 수 : "+threeDArr[0].length+", 열의 수 : "
+threeDArr[0][0].length);
// 일반 for문
for(int i=0; i<threeDArr.length; i++) {
for(int j=0; j<threeDArr[i].length; j++) {
for(int k=0; k<threeDArr[i][j].length; k++) {
System.out.print(threeDArr[i][j][k]+" ");
}
System.out.println();
}
System.out.println();
}
// 향상된 for문
for(int[][] twoDArr : threeDArr) {
for(int[] oneDArr : twoDArr) {
for(int val : oneDArr) {
System.out.print(val+" ");
}
System.out.println();
}
System.out.println();
}
}
public static void main(String[] args) {
new Use3DArray();
}
}
// 배열방의 값을 손쉽게 출력할려면 Arrays 클래스 사용
int[] arr = { 1,2,3,4,5 };
System.out.println(Arrays.toString(arr)); // [1, 2, 3, 4, 5]
참조형 변수의 취약점
- private 배열을 public method로 반환하면 private이 public이 된다!
- 모든 참조형은 이 취약점을 가진다.
// private 배열을 public method로 반환하면 public이 됨!
// 모든 참조형 변수의 취약점
class Test {
// arr의 주소는 한개!, private
private int[] arr = { 1, 2, 3, 4 };
// getter로 private한 arr의 주소를 전달할 수 있음
public int[] getArr() {
// 그대로 return하면 주소가 넘어가기 때문에
return arr;
}
}
public class Test2 {
public static void main(String[] args) {
Test t = new Test();
// 전달받은 주소로 배열을 만들고 값 변경
int[] a = t.getArr();
a[0] = 100;
System.out.println(Arrays.toString(a)); // [100, 2, 3, 4]
int[] b = t.getArr();
System.out.println(Arrays.toString(b)); // [100, 2, 3, 4]
}
}
// 그대로 return하면 주소가 복사되므로 배열을 복사 후 return!
class Test {
private int[] arr = { 1, 2, 3, 4 };
public int[] getArr() {
int[] tmp = new int[arr.length];
for(int i=0; i<arr.length; i++) {
tmp[i] = arr[i];
}
return tmp; // arr의 주소가 아닌 다른 주소를 전달해서 변경을 막음
}
}
public class Test2 {
public static void main(String[] args) {
Test t = new Test();
int[] a = t.getArr();
a[0] = 100;
System.out.println(Arrays.toString(a)); // [100, 2, 3, 4]
int[] b = t.getArr();
System.out.println(Arrays.toString(b)); // [1, 2, 3, 4]
}
}
객체배열
- 클래스로 배열을 생성하는 것
- 여러개의 값을 한번에 관리하기 위해
클래스명[방의번호] 배열명 = new 클래스명[방의번호];
배열명[방의번호] = new 클래스명();
// 모든 방의 값을 출력
for(int i=0; i<배열명.length; i++) {
클래스명 객체명 = 배열명[i];
객체명.getter();//로 값을 얻어 사용
}
/**
* 이름, 나이, 이메일, 성의 이니셜 한자를 저장하는 클래스
*/
public class Data {
private String name;
private int age;
private String email;
private char initial;
public Data() {
System.out.println("Data Default Constructor");
}
public Data(String name, int age, String email, char initial) {
System.out.println("Data Constructor");
this.name = name;
this.age = age;
this.email = email;
this.initial = initial;
}
public String toString() {
return "이름 : "+name+", 나이 : "+age
+", 이메일 : "+email+", 이니셜 : "+initial;
}
// getter, setter..
...
}
import java.util.Arrays;
/**
* 사용자 정의 데이터형(내가 만든 클래스) 사용하여 배열을 생성
* 생성된 배열 방하나는 여러개의 다양한 값을 저장하고 사용할 수 있다.
*/
public class UseClassArray {
public UseClassArray() {
// 1.선언) 데이터형[] 배열명 = null;
Data[] dataArr = null;
// 2.생성) 배열명 = new 데이터형[방의수];
dataArr = new Data[4];
// 3.값할당) 배열명[방의번호] = new 생성자(); 또는
// 클래스명 객체명 = new 생성자();
// 배열명[방의번호] = 객체명;
dataArr[0] = new Data("공선의",27,"gong@daum.net",'G');
dataArr[1] = new Data("김건하",29,"kim@daum.net",'K');
dataArr[2] = new Data("최지우",25,"choi@daum.net",'C');
// 객체생성 후 값을 추가
Data d= new Data();
dataArr[3] = d;
// 주소는 하나이므로 배열명을 사용하여 method 호출하든
dataArr[3].setName("정택성");
dataArr[3].setAge(26);
// 객체명을 사용하여 method를 호출하든 동일하게 값이 변경됨
d.setEmail("jung@jung.net");
d.setInitial('D');
// 4.값사용)
// 배열명으로 바로 사용
System.out.println(dataArr[0].getName()+" / "+dataArr[0].getAge());
// 객체에 저장하여 사용 (권장, 가독성향상)
Data temp = dataArr[0];
System.out.println(temp.getName()+" / "+temp.getAge());
/* // 일괄처리
Data tempData = null;
for(int i=0; i<dataArr.length; i++) {
tempData = dataArr[i];
System.out.println(tempData.getName()+"/"
+tempData.getAge()+"/"
+tempData.getEmail()+"/"
+tempData.getInitial());
}
*/
// 개선된 for문이 훨씬 간단하게 사용가능
for(Data tmp : dataArr) {
System.out.println(tmp.getName()+"/"
+tmp.getAge()+"/"
+tmp.getEmail()+"/"
+tmp.getInitial());
}
}
public static void main(String[] args) {
new UseClassArray();
}
}
OOP 언어의 3대 특징
- 다형성(Polymorphism)
- Overload
- 캡슐화(Encapsulation)
- 접근지정자
- 상속(Inheritance)
- Override
상속
- 부모클래스의 자원(변수, 메소드)을 자식클래스에서 자신의 것처럼 사용하는 것
- 코드의 재사용성 증가
- 클래스간 계층형성
- 부모클래스(super class)
- 자식클래스(sub class)
- 단일 상속만 지원
- 장점 : 부모가 뚜렷, 중복 상속을 방지
- 단점 : 기능 구현에 제약이 생긴다.
- extends 키워드로 자식 클래스에서 부모 클래스를 선택한다.
- 부모클래스에서는 상속받는 자식클래스를 알 수 없다.
- 부모클래스는 공통 특징을 정의
- 자식클래스는 자신만의 특징을 정의
- 다중상속의 기능을 사용할 때는 인터페이스 사용
- 생성자는 상속되지 않는다.
- super키워드로 부모클래스의 자원을 선택하여, 사용할 수 있다.
- 자바 모든 클래스의 부모클래스는 java.lang.Object 이다.
- 자식클래스를 생성하면 부모클래스가 먼저 생성된다.
- 상속관계에 있는 클래스 끼리만 강제형변환이된다.
[접근지정자] class 자식클래스명 [extends 부모클래스명] {
...
}
package date181129; // 같은 패키지, 부모클래스
/**
* 상속관계의 부모클래스 : 모든 자식이 가져야 할 공통 특징 정의
* 부모에게 정의된 코드는 자식에서 사용할 수 있다.
*/
public class TestSuper {
// public - 어디에 있는 자식이든 사용가능
public int public_i;
// protected - 같은 패키지의 자식, 다른 패키지의 자식에서 사용가능
protected int protected_i;
// private - 부모클래스 안에서만 사용가능
private int private_i;
// default - 같은 패키지의 자식에서 사용가능, 패키지가 다르면 사용불가
int default_i;
// 부모클래스를 상속한 자식클래스가 객체화되면
// 부모클래스의 생성자가 먼저 호출 되고 자식클래스의 생성자가 호출
public TestSuper() {
System.out.println("부모클래스 기본생성자");
}
public void superMethod() {
System.out.println("부모클래스의 method");
}
}
package date181129; // 같은 패키지, 자식클래스
/**
* TestSuper의 자식클래스
*/
public class TestSub extends TestSuper {
int i;
public TestSub() {
System.out.println("자식클래스 기본생성자");
}
public void subMethod() {
System.out.println("자식클래스의 method");
}
public static void main(String[] args) {
// 객체화는 자식클래스를 사용한다.
TestSub ts = new TestSub();
// 자식과 부모가 같은 패키지에 존재하면 부모가 가진
// 변수나 method의 접근지정자가 public, protected,
// default인 자원만 사용할 수 있다.
ts.public_i = 10;
ts.protected_i = 20;
ts.default_i = 30;
System.out.println("부모의 자원 "+ts.public_i+"/"
+ts.protected_i+"/"+ts.default_i);
ts.i = 100;
System.out.println("자식의 자원 "+ts.i);
ts.superMethod();
ts.subMethod();
}
}
// 다른패키지! 자식클래스
package date181129.sub;
import date181129.TestSuper; // 다른 패키지이므로 import사용
public class TestSub extends TestSuper{
public static void main(String[] args) {
TestSub ts = new TestSub();
// 자식과 부모가 다른 패키지에 존재하면
// 부모가 가진 변수나 method의 접근지정자가
// public, protected인 자원만 사용 가능
// (캡슐화, Encapsulation)
ts.public_i = 10;
ts.protected_i = 20;
System.out.println("부모의 자원 : "
+ts.public_i+"/"+ts.protected_i);
}
}