오늘은 자바언어의 배열과 사방탐색에 대해서 맛보기로 배웠으며, 객체지향 언어의 다형성,캡슐화에 대해서 배웠다. 수업한지 이틀 지났지만, 지난 기억을 되살려 작성해보겠다.
근데 배열에 앞서 자바에서 배열은? 안쓴다 ㅋㅋ 배열은 그냥 코테 할때만 사용하지 배열은 사용을 잘 안한다. 생각해보니 그렇다.. 서버 개발을 해왔지만 배열은 진짜 잘 안 쓴 거 같다. 그냥 List<> s = ArrayList<>{}; 이거 겁나 썼던 거 같기도 하다..
- int[][] ia; ia = {{10},{2},{3}}; 이렇게는 불가능하다.
- ia = int[][]{{10},{2},{3}} 이렇게는 가능
아래 코드(Arrays.toString)는 꼭 알자! 왜냐? 코테할때 틈틈히 배열에 대해서 작성해서 내가 잘 하고있는지 확인해야하기 떄문이지.. ㅎ
for(int[] a :ia) System.out.println(Arrays.toString(a));
public static void main(String[] args) {
int[][] ia = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
//2방탐색 :2 8
for(int i=0; i<ia.length;i++) {
for(int j=0;j<ia[i].length;j++) {
if(ia[i][j]==5) {
System.out.println(ia[i-1][j+0]); //2
System.out.println(ia[i+1][j+0]); //8
int[] di = {-1,1};
int[] dj = {0,0};
for(int d=0;d<1;d++) {
int ni =i+di[d];
int nj =i+dj[d];
System.out.println(ia[ni][nj]);
}
}
}
}
//2방탐색 : 6 4
for(int i=0; i<ia.length;i++) {
for(int j=0;j<ia[i].length;j++) {
if(ia[i][j]==5) {
System.out.println(ia[i+0][j+1]); //6
System.out.println(ia[i+0][j-1]); //4
int[] di = {0,0};
int[] dj = {1,-1};
for(int d=0;d<1;d++) {
int ni =i+di[d];
int nj =i+dj[d];
System.out.println(ia[ni][nj]);
}
}
}
}
//4방탐색 : 2 6 8 4
for(int i=0; i<ia.length;i++) {
for(int j=0;j<ia[i].length;j++) {
if(ia[i][j]==5) {
System.out.println(ia[i-1][j+0]); //2
System.out.println(ia[i+0][j+1]); //6
System.out.println(ia[i+1][j+0]); //8
System.out.println(ia[i+0][j-1]); //4
int[] di = {-1,0,1,0};
int[] dj = {0,1,0,-1};
for(int d=0;d<4;d++) {
int ni =i+di[d];
int nj =i+dj[d];
System.out.println(ia[ni][nj]);
}
}
}
}
// 8방탐색 : 2,3,6,9,8,7,4,1
for (int i = 0; i < ia.length; i++) {
for (int j = 0; j < ia[i].length; j++) {
if (ia[i][j] == 5) {
System.out.println(ia[i - 1][j + 0]); // 2
System.out.println(ia[i - 1][j + 1]); // 3
System.out.println(ia[i + 0][j + 1]); // 6
System.out.println(ia[i + 1][j + 1]); // 9
System.out.println(ia[i + 1][j + 0]); // 8
System.out.println(ia[i + 1][j - 1]); // 7
System.out.println(ia[i + 0][j - 1]); // 4
System.out.println(ia[i - 1][j - 1]); // 1
System.out.println("---------");
// 상우하좌 - 시계 방향
int[] di = { -1, -1, 0, 1, 1, 1, 0, -1 };
int[] dj = { 0, 1, 1, 1, 0, -1, -1, -1 };
for (int d = 0; d < 8; d++) {
int ni = i + di[d];
int nj = j + dj[d];
System.out.println(ia[ni][nj]);
}
}
}
}
}
위에 보이는 것처럼 사방탐색에 대해서 짧게나마 코드를 적었다.
여기서 중요한 점은 중심을 기준으로 상우하좌 이것이다. 뭐 이해하면 좋겠지만, 이해가 되지 않는다면 외우자 나도 알고리즘을 잘 공부를 안했어서 몰랐는데 dfs 문제 풀때 사용한다고 한다.
int[] di = {-1,0,1,0};
int[] dj = {0,1,0,-1};
// 변하지 않는 값 -> 상수로 만들어 줌 final
// 상우하좌 - 시계 방향
static final int[] di = { -1, 0, 1, 0 };
static final int[] dj = { 0, 1, 0, -1 };
public static void main(String[] args) {
int[][] ia = { { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 9, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, };
for (int[] a : ia)
System.out.println(Arrays.toString(a));
System.out.println("--------------");
int N = ia.length;
int M = ia[0].length;
// 4방탐색 : 상우하좌
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (ia[i][j] == 9) {
for (int k = 1; k <= 3; k++) {
for (int d = 0; d < 4; d++) {
int ni = i + di[d] * k;
int nj = j + dj[d] * k;
if (ni >= 0 && nj >= 0 && ni < N && nj < M) {
ia[ni][nj] = k;
}
}
}
}
}
}
for (int[] a : ia)
System.out.println(Arrays.toString(a));
}
}
위와 같이 상후하좌값을 상수로 만들어서 사용도 가능하다.
Arrays.copyOf(ia,ia.length);
- 첫번 째, 접근지정자를 private로 필드명으로 만들어서, 다른 곳에서 잘못된 값으로 값을 바꾸지못하게 접근을 제한한다.
- 두번 째, public한 부분을 최소하게 적용해라.
- 세번 째, 유효성을 적용해라이다.
이에 person이라는 클래스를 만들었다.
public sealed abstract class Person implements Serializable permits Student, Teacher, Employee{
private String name = "아무개";
private int age;
public Person(String name,int age) {
setName(name);
setAge(age);
}
public Person(String name) {
this(name,99);
}
public Person() {
this("모지리",99);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
checkAge(age);
}
private void checkAge(int age) {
if(age<1 || 99<age){
System.out.println("invalid age(1~99): "+age);
System.exit(0);
}else{
this.age=age;
}
}
@Override
public String toString() {
return getName()+"\t"+getAge()+"\t";
}
public void printAll() {
//System.out.println(this.toString());
//System.out.println(toString());
System.out.println(this);
}
}
위 코드에서 public Person(String name){this.(name,9)}생성자 메소드에서this.(name,9)는 ublic Person(String name,int age)이를 호출하는 것입니다.
그리고 잘 보시면 필드명을 private로 지정하여 접근을 제한하였으며,
public void setAge(int age) {
checkAge(age);
}
해당 코드로 나이에 접근할 수있도록 해놓았습니다. 그리고 private void checkAge(int age) {} 코드로 해당 age의 유효성을 검사하고있습니다. 근데 이는 나중에 @Vaild 어노테이션을 사용하여, controller에서 검사하면 되는 거지싶다.
< Person을 상속하는 클래스 선언>
public non-sealed class Teacher extends Person {
private String subj;
public Teacher(String name, int age, String subj) {
super(name,age);
setSubj(subj);
}
public Teacher(String name, String subj) {
this(name,99,subj);
}
public Teacher(String name) {
this(name,99,"무전공");
}
public Teacher() {
this("모지리",99,"무전공");
}
public String getSubj() {
return subj;
}
public void setSubj(String subj) {
this.subj = subj;
}
@Override
public String toString() {
return super.toString()+getSubj();
}
}
여기서 super가 있는데 우리가 Teacher t = new Teacher();로 객체를 생성한다면, teacher만 힙메모리에 생성되는줄 아는데 그렇게 하면, 어떻게 상속된 Person의 필드를 사용하는가??? 그럼 person는 언제 생성하지? 라는 생각이 든다. 이는 super에서 사용된다. Teacher를 생성할 때, default생성자에는 super()가 생략되어있다. 그래서 super()로 person을 생성하고 teacher를 생성하게 된다. 그럼 만약 default 생성자가아닌, 매개변수가 포함되어있느 경우에는 super를 따로 선언해줘야한다.
- 변수를 선언할때 부모로 선언하자 (Person p = new Student)
- 변수를 선언할때 부모타입으로 선언한다.(배열)
- 파라미터를 선언할때 부모타입으로 선언하면 자식꺼 다 넣을 수 있음.
Person[] pa = new Person[3];
pa[0] = new Student("홍길동",20,23123);
pa[1] = new Teacher("홍길동",20,"자바");
pa[2] = new Employee("홍길동",20,'A');