-
java 교육 5일카테고리 없음 2025. 5. 26. 15:50
[교육 1일차]
java 기본 개념 교육 c언어와 비교하며 수업해주셨다.
c언어 실행방법 : gcc test01.c -o a.exe 후 a.exe
주의사항 ) gcc있어야함. gcc 경로를 못 찾아서 path설정을 해줬다. 환경변수 path에 gcc bin 폴더경로 추가 후 cmd창 닫고 다시 cmd 열면 해결됨
java 실행방법 : javac test02.java 후 java test02
test01 .c
#include <studio.h> int main() { int a ; a = 100; printf("%d\n", a) ; return 0; }test04.java
public class test04 { public static void main (String[] args){ int a; a = 10; System.out.println(a); double b = 3.143; System.out.println(b); } }test05 .c
#include <stdio.h> int main(){ int a ; int *b, *c; a=100; b= &a; c= b; printf("%d %d %d", a, *b, *c); return 0; } /* 포인터는 기억공간을 가리킬 수 있는 변수이다 (이름 아님)- 삼각형 기억공간으로 표현 c=b 포인터의 대입은 오른쪽이 가리키는 대상을 왼쪽이 가리키게 된다 */test06 .c
#include <stdio.h> struct ab { int a; float b; }; int main(){ struct ab apple; struct ab *t; apple.a = 100; apple.b = 3.14; t= &apple; t->b = 0.066; printf("%d %f\n", apple.a, apple.b); return 0; } /* apple이름으로 변수 선언 - struct ab 형태의 공간을 확보한다 a라는int형 변수와 b라는 float형 변수가 함께 있는 복합공간 구조체는 자료형처럼 이해하고 사용하면 됨. java 클래스는 알고보면 구조체다. 따라서 클래스는 자료형처럼 이해하면 된다. */test07.c
#include <stdio.h> /* 구조체는 자료형처럼 쓸 수 있기에 typedef 를 적용할 수 있다 이러면 마치 AB라는 새로운 자료형을 만든 것처럼 사용이 가능하다 메모리 확보 방법 1. 변수선언 - 자료형 or 구조체, 이름(심볼) 필수 int a ; b=&a; 기억공간에 대한 포인터는 존재한다 2. malloc - 자료형 or 구조체, 이름(심볼) 없음. 이름이 없이 포인터로만 접근 가능하다. */ typedef struct ab { int a; float b; }AB; int main(){ AB apple; AB *t; apple.a = 100; apple.b = 3.14; t= &apple; t->b = 0.066; printf("%d %f\n", apple.a, apple.b); return 0; } /* apple이름으로 변수 선언 - struct ab 형태의 공간을 확보한다 a라는int형 변수와 b라는 float형 변수가 함께 있는 복합공간 구조체는 자료형처럼 이해하고 사용하면 됨. java 클래스는 알고보면 구조체다. 따라서 클래스는 자료형처럼 이해하면 된다. */test08.c
#include <stdio.h> typedef struct ab { int a; float b; }AB; int main(){ AB *t; t = (AB*)malloc(sizeof(AB)); // AB형태의 메모리를 확보하여 포인터를 리턴한다 t->a = 9999; t->b = 193.23412345; printf("%d %f \n", t->a, t->b); free(t); //malloc으로 확보된 기억공간은 free로 소거한다 // t(삼각형)을 날리는 게 아니라 t가 가리키는 대상(박스)가 날아간다 return 0; }test09.java
class AB{ int a; double b; } public class test09{ public static void main(String[] args){ AB t = new AB(); t.a=100; t.b = 3.14; System.out.println(t.a + ", "+ t.b); } }test10.c
typedef struct node { int data; struct node *next; // 가능 }Node; int main(){ Node* head; head= (Node*)malloc(sizeof(Node)); head->data = 0; head->next = (Node*)malloc(sizeof(Node)); head->next->data = 100; printf("%d, %d", head->data, head->next->data); free(head->next); // head포인터가 가리키는 malloc된 대상 안의 next 포인터가 가리키는 대상을 날려라 free(head); return 0; }test11.java
class Node{ int data; Node next; } public class test11{ public static void main(String[] args){ Node head = new Node(); head.data = 100; head.next = new Node(); head.next.data = 200; System.out.println(head.data + ", "+ head.next.data); } }test15.java
class Node{ int data; Node next; } // 클래스(구조체), 인스턴스(malloc), 멤버변수, 참조형변수(포인터) 개념 클래스 안에서 생선한 변수 멤버변수. 멤버변수는 인스턴스를 생성할 때 할당받는다 클래스 이름으로 생성된 변수를 참조형변수라고 한다 인스턴스를 가리키기 위한 용도이다..................... public class test15{ public static void main(String[] args){ Node head ; // 클래스 이름으로 선언한 변수는 참조형변수, new로 할당받은 메모리 공간을 가리키는 용도 head = new Node(); // new는 malloc과 유사 // 클래스 안에는 변수를 선언할 수 있다. 이 변수는 new할 때 메모리를 할당받는다. // new Node(); 형태로 만들어진 할당받은 메모리 공간을 인스턴스 라고 한다. // 클래스는 구조체다. 여러번 선언 가능하다. 즉, 여러번 인스턴스 생성 가능하다. // 여러번 인스턴스 만들어질 때마다 새로 변수가 생긴다. // 클래스 안에서 선언된 변수를 멤버변수라고 한다. // 멤버변수는 인스턴스 생성할 때마다 메모리를 할당받는다 System.out.println(head.data + ", "+ head.next.data); } } /* java의 class는 알고보면 구조체다 : 변수 선언이 가능 (대입연산금지) class이름으로 변수를 선언할 수 있다. 자료형으로 뭘 할 수 있었지? 변수 선언. 포인터 선언. malloc선언. 가능 구조체로 뭘 할 수 있었지? 변수, 포인터, malloc선언 java는 이 중 변수 선언만 안된다. 이 점이 c와 차이점 ! 구조체는 마치 자료형처럼 쓰는구나... typedef 클래스는 변수 선언이 빠진 구조체더라.. */test16.java
class Node{ int data; Node next; } public class test16{ public static void main(String[] args){ Node head = new Node(); Node tail = head; Node t = new Node(); t.data = 10; t.next = null; tail.next = t; tail = tail.next; t = new Node(); t.data = 20; t.next = null; tail.next = t; for(t= head.next; t != null ; t = t.next){ System.out.println(t.data); } } }test16.java -> c로 작성
#include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next ; }Node; int main(){ // Node* head, tail, t; Node* head = (Node*)malloc(sizeof(Node)); Node* tail = head; Node* t = (Node*)malloc(sizeof(Node)); t->data = 10; t->next = Null; tail->next = t; tail = t->next; Node* t = (Node*)malloc(sizeof(Node)); t->data = 20; t->next = Null; tail->next = t; for(t= head->next; t != Null ; t = t->next){ printf("%d\n", t->data); } free(head); free(tail); free(t); return 0; }test17.c
#include <stdio.h> int add(int i, int j){ printf("->%d\n", i); printf("->%d\n", j); return i+j; } int main() { int r ; r = add(10,20); printf("%d ", r); return 0; } /* add(10,20) 이 호출되면?? 1. int i, int j; 선언 - 메모리할당 2. i = 10; j = 20 ; 대입 3. 활용 4. return 값; 값이 함수를 호출한 add(10,20) 부분을 대신한다고 보면 실수가 없다. */함수포인터
test20.c
구조체 안에 함수 선언 불가능하다
#include <stdio.h> typedef struct apple { int data; //int add(int, int); // error 함수선언 불가능 }Apple; int add(int i, int j){ return 100; } int add_v2(int i, int j){ return 200; } int main() { int (*fp)(int, int); fp = add; printf("%d ", fp(10,20)); fp = add_v2; printf("%d ", fp(10,20)); return 0; } /* int (*fp)(int, int); 함수포인터 fp는 포인터 변수다. 기억공간이 아닌 함수를 가리킨다. 매개변수가 int int 이고 리턴타입이 int인 fp = add; 이 코드는 fp포인터가 add라는 함수를 가리키도록 대입한 코드 결과값 100 return fp(10,20) fp포인터가 가리키는 함수를 호출한다 ..라는 이야기다. add_v2추가하면? 결과값 100 200 return 유지보수가 유독 많은 함수에 함수포인터를 이용하면 유지보수성이 좋아진다. *** 구조체 안에 함수 선언 안된다 !!!!!!!!!!!!! */구조체 안에 함수 선언 불가능하지만 !!!!!!!!
함수포인터는 구조체 안에 선언 가능
test21.c
#include <stdio.h> typedef struct apple { int data; int (*add)(int, int); // 가능! 함수포인터는 구조체 안에 선언이 가능하다 }Apple; int Apple_add(int i, int j){ return 100; } int main() { Apple* t; t = (Apple*)malloc(sizeof(Apple)); t->data = 0; t->add= Apple_add; printf("%d %d \n", t->data, t->add(10,20)); return 0; } /* t->add(10,20) 함수 포인터를 이용하면 마치 t가 가리키는 대상 안에 add라는 이름의 함수를 호출하는 것 같은 모양을 만들 수 있다 java는 class안에 함수 선언이 가능하다. 위와 같은 방법으로 호출할 수 있다. t.add(10,20); */한번 만들어진 메모리 재사용할 때
단순 데이터 재사용하는 것과
이 데이터를 operation할 수 있는 것과
함수 재사용하는 것과 뭐가 더 효율적일까? 2일차 수업에서 계속..[교육 2일차]
클래스
인스턴스
참조형변수
멤버변수
멤버함수
new
this
클래스 안에 올 수 있는 코드? 변수선언가능(멤버변수 / 대입은 불가), 함수선언가능(멤버함수 / 호출은 불가)
=> 클래스는 알고보면 구조체, 함수포인터 이용해서 구조체 안에 함수를 밀어 넣음
클래스로 뭐 할 수 있나? (변수선언 포인터선언 malloc = java에선 변수선언 빠짐)
- 포인터 선언 ( 클래스 이름으로 선언된 변수 - 클래스로 선언된 변수는 100%포인터다. 이를, 참조형변수라 한다.)
- 클래스 이름으로 선언된 변수는 인스턴스를 가리키게 된다
new와 malloc은 유사하다. 선언된 클래스 대로 메모리를 할당받은 실체가 인스턴스
멤버변수는 언제 메모리 할당받나? 인스턴스를 생성할때마다.
멤버변수는 어떻게 호출 ? 인스턴스 생성 + 참조형 변수를 이용 + 이름과 매개변수로 호출, this 사용가능
this는 알고보면 로컬변수이고, 호출 때마다 가리키는 대상이 달라지고, 호출된 함수를 포함하는 인스턴스를 가리키게 된다.test22.c
#include <stdio.h> typedef struct ab { int a; float b; }AB; int main(){ int a; int *b; AB ab; AB *p; p = (AB*)malloc(sizeof(AB)); ab.a = 100; p->b = 3.14; b= (int*)malloc(sizeof(int)); *b = 100; // 변수는 이름 있지만 malloc으로 만든 공간은 이름이 없기에 포인터로 접근해야한다 a=200; a = a + 100; return 0; } /* 변수는 이름 있지만 malloc으로 만든 공간은 이름이 없기에 포인터로 접근해야한다 구조체 : 변수, 포인터, malloc */test23.java
class AB{ int a; double b; } public class test23{ public static void main(String[] args){ AB p = null p = new AB(); } } /* 클래스: 변수 모든 포인터에는 null값 대입 가능하다. 포인터는 인스턴스를 가리킨다 참조형변수는 클래스 이름으로 선언됐고 */test24.java
class Apple{ int data= 0; int add(int i){ return 100; } } public class test24{ public static void main(String[] args){ Apple t = null; t = new Apple(); t.data = 100; System.out.println(t.add(10)); } } /* 클래스 안에 선언된 함수를 호출하려면?? 1. 인스턴스 생성 2. 참조형 변수로 가리키고 3. 참조형변수. 함수명(매개변수값); 형태로 호출한다 */test25.c
#include <stdio.h> typedef struct apple{ int data; //int add (int i) {return 10101;} // c언어는 구조체 안에 함수 return 못함 -> 별도 함수로 외부에 작성하고 포인터로 선언해줘야함. int (*add)(int); }Apple; int Apple_add(int i){ return 10101; } int main(){ Apple* t; // 포인터 선언 t = (Apple*)malloc(sizeof(Apple)); // 메모리할당 t->data = 100; //데이터 t->add = Apple_add; printf("%d", t->add(100)); free(t); return 0; }test26.java
class Apple{ int data= 23; int add(int i){ return (this.data + 10101 ); } } public class test26{ public static void main(String[] args){ Apple t = null; t = new Apple(); t.data = 100; System.out.println(t.add(10)); } } /* this.data this는 변수 아님 t.data = 100; 과 비교해보면 여기서 this는 Apple형 포인터이어야 한다!! this.data는 100이면 이 결과가 말이 된다(10201) this 포인터는 호출된 함수 포인터를 소유하고 있는 인스턴스를 가리키는 포인터 이어야 한다 !! (쉽게 얘기하면 자기 자신에 대한 포인터가 된다) print값이 10124일까 10201일까? 10201 t포인터에 data 100으로 값 다시 초기화한 후, add함수 호출한 것이기 때문. this.data는 자기자신의 함수포인터가 되어 Apple클래스를 가리키고 data는 100으로 재호출.... */test27.c
#include <stdio.h> typedef struct apple{ int a; int b; int c; int (*sum)(int, int, int); }Apple; int apple_sum(int a, int b, int c){ return a+b+c; } int main(){ Apple* t; // 포인터 선언 t = (Apple*)malloc(sizeof(Apple)); // 메모리할당 t->a = 10; t->b = 20; t->c = 30; t->sum = apple_sum; printf("%d", t->sum(t->a, t->b, t->c)); free(t); return 0; } /* 이렇게 함수를 만들면 굳이 구조체로 묶을 필요도 없고, 변수가 추가되면 다시 짜야한다 */test28.c
#include <stdio.h> typedef struct apple{ int a; int b; int c; int x; int (*sum)(struct apple*); }Apple; int apple_sum(Apple* this){ return this->a + this->b + this->c + this->x; } int main(){ Apple* t; // 포인터 선언 t = (Apple*)malloc(sizeof(Apple)); // 메모리할당 t->a = 10; t->b = 20; t->c = 30; t->x = 55; t->sum = apple_sum; printf("%d", t->sum(t)); free(t); return 0; } /* c언어로 객체지향 프로그래밍 할 때, 구조체 안에서 선언된 모든 함수 포인터의 첫번째 매개변수는 같은 타입의 포인터로 선언한다 t->sum(t) 호출할 때, 사용한 포인터를 같이 넘긴다. Apple* this = t ; this는 t가 가리키는 대상을 가리킨다. this 포인터는 sum 함수 포인터가 소속된 인스턴스 안의 모든 함수와 변수에 접근이 가능하다 x변수를 추가한다고 생각하면 유지보수성이 좋아지더라 */test29.java
class Apple{ int data= 23; void print(){ System.out.println(this.data); } } public class test29{ public static void main(String[] args){ Apple a= new Apple(); a.data = 100; a.print(); Apple b= new Apple(); b.data =200 ; b.print(); } } /* */test30.c
#include <stdio.h> int main(){ int a[4]; int i; int temp, max; // 3 1 4 2 a[0] = 3; a[1] = 1; a[2] = 4; a[3] = 2; max = 0; if (a[max] < a[1]) { // 3<1 max = 1; //x } if (a[max] < a[2]) { // 3<4 max = 2; // max= 2 } if (a[max] < a[3]) { // 4<2 max = 3; } // max = 2 //printf("1) max a[max] : %d %d", max, a[max]); // 2 4 if(max != 0){ temp = a[0]; // 3 a[0] = a[max]; // a[0] = 4 a[max] = temp; // a[2] = 3 } for(i = 0; i < 4; i++){ printf("%d\n", a[i]); } // 4 1 3 2 return 0; }test31.c
#include <stdio.h> void print(int* t){ int i; for (i = 0; i < 3; i++){ printf("print() : %d\n", *(t+i)); } //printf("print() : %d\n", *t); } int main(){ int a[2]; int i; int *p; p = a ; // 배열형 변수는 사실은 포인터다 a[0] = 10; a[1] = 20; a[2] = 30; printf("%d\n", *p); // 배열형 변수가 대입된 포인터는 배열의 첫번째 요소를 가리킨다 printf("%d\n", *(p)); // printf("%d\n", *(p+0)); // a[0] printf("%d\n", *(p+1)); // a[1] for(i = 0; i < 3; i++){ printf("%d\n", a[i]); } // print(a); return 0; }test32.c
#include <stdio.h> void add(int* t){ // ??? } void print(int* t){ printf("print() : %d\n", *(t+0)); printf("print() : %d\n", *(t+1)); //int i; //for (i = 0; i < 3; i++){ // printf("print() : %d\n", *(t+i)); //} //printf("print() : %d\n", *t); } void sort(int* t){ int t; if (*(t+0) < *(t+1)){ // 동일 코드 : data[0] < data[1] t = *(t+0); *(t+0) = *(t+1); *(t+1) = t } } int main(){ int a[2]; add(a, 0, 100); add(a, 1, 200); sort(a); print(a); return 0; } /* 이 코드에서 add 없는 print함수는 의미가 없다 add 없는 sort도 의미가 없다 배열 없는 add도 의미 없다 배열 + add + sort + print가 한 덩어리로 묶여서 재사용되는 빈도가 훨씬 많더라 -> 객체지향적으로 이 부분을 해결해보자 */test33.java
public class test33{ public static void main(String[] args){ int[] data = new int[2]; int[] t = data; data[0] = 100; t[1] = 200; System.out.println(data[1]); System.out.println(t[0]); } } /* int[] data = new int[2]; 배열은 인스턴스이다 (new) data는 배열을 가리키는 참조형 변수가 된다 (포인터) */test34.java
/* java는 변수와 함수가 독립적으로 존재할 수 없다. 클래스 안에서 선언되어야 한다. 멤버함수 안에서는 this를 쓸 수 있고 t.add(0,100) 형태로 호출됐을 때, add함수 안의 this는 t와 같은 대상을 가리키게 된다. add, sort, print는 data배열과 뗄레야 뗄 수 없는 관계가 성립된다. 자연스럽게 한 묶음이 되고, 재사용성이 늘어나게 된다. */ class Banana{ int[] data = null; void add(int idx, int val){ this.data[idx] = val; } void print(){ System.out.println(this.data[0] + "," + this.data[1]); } void sort(){ if (this.data[0] < this.data[1]){ int temp = this.data[0]; this.data[0] = this.data[1]; this.data[1]= temp; } } } public class test34{ public static void main(String[] args){ Banana t = new Banana(); t.data = new int[2]; t.add(0,100); t.add(1,200); t.sort(); t.print(); } }test35.c
#include <stdio.h> typedef struct banana{ int *data; void (*add)(struct banana*, int, int); void (*print)(struct banana*); }Banana; int banana_add(Banana* this, int idx, int val){ //this->data[idx] = val; *(this->data+idx)= val; } /* void print(Banana* this){ pirntf(this.data[0] + "," + this.data[1]); } */ Banana* new_Banana(){ Banana* t; t= (Banana*)malloc(sizeof(Banana)); t->add = Banana_add; t->data = (int*)malloc(sizeof(int)*2); return t; } int main(){ Banana* b; // 포인터 선언 t = (Banana*)malloc(sizeof(Banana)); // 메모리할당 t->add(t, 0, 100); free(t); return 0; } /* 이렇게 함수를 만들면 굳이 구조체로 묶을 필요도 없고, 변수가 추가되면 다시 짜야한다 c언어로 객체지향스럽게 코드를 짠 예 c언오로 구조체와 함수포인터를 사용하여 객체지향 적으로 개발할 수도 있다 하지만 애초에 객체지향 프로그래밍을 목적으로 만든 언어를 사용하는 것이 더 적합하다 이코드는 객체지향 언어의 주요개념들(클래스 인스턴스 멤버변수 멤버함수 this new 등)을 이해하기 위한 목적으로 사용하자 */test36.java
class Apple{ int data; // 멤버변수 Apple(int i ){ // 생성자함수 : 인스턴스 생성시 호출됨 System.out.println("Apple " + i); this.data = i; } } public class test36{ public static void main(String[] args){ Apple t = null; Apple x = new Apple(100); Apple y = new Apple(200); System.out.println(x.data + ", " + y.data); //x.Apple(0); // 에러. 생성자함수는 멤버함수가 아니어서 포인터로 호출될 수 없다. } } /* 클래스 이름과 같고, 리턴타입이 없다 -> 생성자함수 (Constructor)이라고 한다. 호출될 수 있지만 멤버함수가 아니다. -> 인스턴스 생성시에 호출된다(매번) 생성자 함수에는 매개변수를 선언할 수 있고, 생성자 함수에 값을 전달할 수 있고 -> "주로(대부분) 멤버변수를 초기화하는 용도로 사용된다." */test38.java
class Node{ int data = 0; Node next = null; /* Node(int a){ this.data=a; }*/ Node(int a, Node b){ this.data=a; this.next=b; } } class LinkedList{ Node head = null; Node tail = null; Linkedlist(){ this.head = new Node(0,null); this.tail = this.head; } void add(int i){ this.tail.next = new Node(i, null); } public class test38{ public static void main(String[] args){ //Node head = new Node(99); //System.out.println(head.data); //Node head2 = new Node(42, null); //System.out.println(head2.data); LinkedList l = new LinkedList(); l.add(10); l.add(20); l.add(30); } } /* */test39.c
#include <stdio.h> int main(){ int a, *p; float b; void *vp; a=10; p = &a; // 당연 int* 변수가 int형 공간을 가리킨다 vp = &a; // void* 형 변수가 int공간을 가리킨다 printf(" %d\n", *p); // printf("%d\n", *vp); // 에러. void*형은 반드시 타입 형변환 시킨 후 사용해야함. printf(" %d\n", *((int*)vp)); b = 3.14; vp = &b; // void*형 변수는 모든 형태의 기억공간을 가리킬 수 있다. printf("%d\n", *((float*)vp)); printf("%d\n", *((int*)vp)); }[교육 3일차]
test41.java
class Dog{ int weight=500; } public class test41{ public static void main(String[] args){ Dog mary = new Dog(); mary.weight = mary.weight + 12; System.out.println(mary.weight); Dog happy = mary; happy.weight = happy.weight + 59; System.out.println(happy.weight); } } /* 인스턴스가 가진 메모리는 인스턴스를 가리키는 참조형 변수의 개수가 0이 되는 순간에 회수한다 (가비지콜렉터 라는 메커니즘이 있고 이것은 자바 실행머신에서 활동한다) 실제로 소거하는 시점은? CPU가 놀 때(할일없음), 메모리가 부족(배고파 죽겠다) main이 끝나서 mary happy 두 포인터가 자동으로 없어진다 (로컬변수) 따라서 new Dog()로 생성한 메모리가 밥줄이 끊기고 -> 포획되고 -> 소거된다 없앨 수는 없지만 잡혀가게 할 수는 있다 -> 가리키는 포인터의 개수를 0으로 만들면 된다. */test42.java
class Node{ int data = 0; Node next = null; Node(int a, Node b){ this.data=a; this.next=b; } } public class test42{ public static void main(String[] args){ Node head = new Node(0,null); Node tail = head; tail.next = new Node(10,null); tail = tail.next; tail.next = new Node(20,null); tail = tail.next; tail.next = new Node(30,null); tail = tail.next; for(Node t = head.next; t != null ; t = t.next){ System.out.println(t.data); } Node a = head ; Node b = head.next; while(a != null){ a.next = null; a=b; b=b.next; } tail = head; } } /* */test43.c
#include <stdio.h> typedef struct node { int data; struct node *next; }Node; Node* new_Node(int i, Node* b){ Node* t; t= (Node*)malloc(sizeof(Node)); t->data = i; t->next = b; return t; } int main(){ Node *head, *tail, *t; Node *a, *b; head = new_Node(0,Null); tail = head; tail->next = new_Node(10, Null); tail = tail->next; tail->next = new_Node(20, Null); tail = tail->next; tail->next = new_Node(30, Null); tail = tail->next; // 어디에 어떻게 코드를 한 줄 짜면 싹 다 지울 수 있을까? a= head; b = head->next; while (a!=Null){ a=b; b=b->next; } for(t= head->next ; t != Null ; t->next){ printf("%d\n", t->data); } free(head); return 0; }test44.java
class A{ int data = 100; } /* 상속 : 클래스가 가진 멤버변수와 멤버함수를 물려받는 것 */ class B extends A{ void print(){ System.out.println("print"); } } public class test44{ public static void main(String[] args){ A a = new A(); //a.print(); // error B b = new B(); System.out.println(b.data); b.print(); /* 조상 클래스형 포인터로 자손 클래스의 인스턴스를 가리킬 수 있다. (상속 받은 클래스가 자손, 상속을 준 클래스가 조상) 이때 조상에서 선언된 함수와 변수가 접근 가능하다. */ A ab = new B(); // ab.print(); 분명 print 함수 포인터가 있는데도 접근이 안된다 System.out.println(ab.data); // B ac = new A(); // error 자손은 조상에게 상속만 받을 수 있음. } }test46.c
#include <stdio.h> #include <stdlib.h> typedef struct a { int data; }A; typedef struct b { int data; // 상속되어서 물려받은 멤버변수 void (*print)(void); // 자손에서 추가된 멤버함수 }B; int main(){ void* vp; A* a; B* b; vp = malloc(sizeof(B)); a = (A*)vp; printf("%d\n", a->data); //a->print(); // error 조상은 조상까지만 접근가능 b=(B*)vp; b->print(); // 자손은 조상+자손 접근가능 return 0; }test47.c
#include <stdio.h> #include <stdlib.h> typedef struct a { int data; }A; typedef struct b { int data; // 상속되어서 물려받은 멤버변수 void (*print)(void); // 자손에서 추가된 멤버함수 }B; void a_print(){ printf("apple\n"); } void* new_a{ A* t; t = malloc(sizeof(A)); t->data=100; t->print = a.print; return t; } int main(){ A* a; a=(A*)new_a(); printf("%d\n", a->data); a->print(); return 0; }test48.c
#include <stdio.h> #include <stdlib.h> typedef struct a { int data; }A; // 상속은 골라받을 수 없다. 그대로 순서대로 온 다음 자손에서 추가된 것을 넣어준다. typedef struct b { int data; // 상속되어서 물려받은 멤버변수 void (*print)(void); // 자손에서 추가된 멤버함수 void (*print2)(void); }B; void a_print(){ printf("apple\n"); } void b_print(){ printf("banana\n"); } void* new_a(){ A* t; t = malloc(sizeof(A)); t->data=100; t->print = a.print; return t; } void* new_b(){ B* t; t = malloc(sizeof(t)); t->data=444; t->print = a_print; t->print = b_print; return t; } int main(){ A* a; B* b; a=(A*)new_a(); printf("\n%d\n", a->data); a->print(); printf("\n%d\n", b->data); b->print(); b=(B*)new_b(); printf("\n%d\n", b->data); a->print(); return 0; }test49.java
class A{ void print(){ System.out.println("apple"); } } class B extends A{ void print(){ System.out.println("banana"); } } public class test49{ public static void main(String[] args){ B b = new B(); b.print(); // banana } }test50.c
#include <stdio.h> #include <stdlib.h> typedef struct a { void (*print)(void); }A; void a_print(){ printf("apple\n"); } void b_print(){ printf("banana\n"); } void* new_a(){ A* t; t= (A*)malloc(sizeof(A)); t->print = a_print; return t; } typedef struct b { void (*print)(void); }B; // 오버라이딩이 일어난 경우에는 함수포인터를 선언하지 않는다 void* new_b(){ B* t; t= (B*)malloc(sizeof(B)); t->print = a_print; // 물려받는다 t->print = b_print; // 오버라이딩의 실체 // 포인터는 물려받은 거, 가리키는 실체는 자손에서 추가된 것 return t; } int main(){ A* a; B* b; a=(A*)new_a(); a->print(); b=(B*)new_b(); a->print(); b->print(); return 0; } /* 결과 apple apple banana */test51.java
class A{ void print(){ System.out.println("apple"); } } class B extends A{ void print(){ System.out.println("banana"); } void print2(){ System.out.println("orange"); } } public class test51{ public static void main(String[] args){ A a = new A(); a.print(); B b = new B(); b.print(); // banana b.print2(); A ab = new B(); ab.print(); //ab.print2();//error } } /* apple banana orange banana 조상의 포인터로 자손의 인스턴스를 가리킬 수 있다. 조상에서 선언된 멤버변수 멤버함수만 접근 가능하다. 만일 오버라이딩 된 경우에는 오버라이딩 된 함수가 호출된다. */tset52.java
class Node{ int data = 0; Node next = null; Node(int a, Node b){ this.data=a; this.next=b; } } class LinkedList{ Node head = null; Node tail = null; LinkedList(){ head = new Node(0,null); tail=head; } void add(int a){ tail.next = new Node(a, null); tail = tail.next; } void print(){ for (Node t = head.next; t != null; t=t.next){ System.out.println(t.data); } } } class LinkedList2 extends LinkedList{ void add(int a){ head.next = new Node(a, head.next); } } public class test52{ public static void main(String[] args){ LinkedList l = new LinkedList(); l.add(10); l.add(20); l.add(30); l.print(); /* 10 20 30 */ LinkedList l2 = new LinkedList2(); l2.add(10); l2.add(20); l2.add(30); l2.print(); /* 30 20 10 */ } } /* */test53.java
class A{ A(){ System.out.println("a"); } } class B extends A{ B(){ System.out.println("b"); } } public class test53{ public static void main(String[] args){ new B(); } } /* 결과 a b 생성자함수는 인스턴스를 생성했을 때 (new) 호출된다. 자손의 인스턴스를 생성했다 -> 조상의 생성자 호출되고, 자손의 생성자가 호출된다. 생성자함수: 멤버변수 초기화 용도 -> 조상의 멤버변수는 조상의 생성자에서, 자손의 멤버변수는 자손의 생성자에서 각각 초기화 한다. */test54.java
class A{ int apple = 1; A(int i){ this.apple = i; } } class B extends A{ int banana = 4; B(int i, int j){ //this.apple = j; // error super(j); // this.banana = i; } } public class test54{ public static void main(String[] args){ B b = new B(100,200); System.out.println(b.apple); System.out.println(b.banana); } } /* 200 100 조상의 멤버변수는 조상의 생성자에서, 자손의 멤버변수는 자손의 생성자에서 각각 초기화한다. B는 apple, banana 두개의 멤버변수를 가지고 있다. 자손의 인스턴스를 생성하면 조상의 '디폴트로 매개변수 없는 생성자'가 호출된다 A(){...} 생성자가 선언딘 적이 없다. <- 에러가 났다 */조상의 멤버변수는 조상의 생성자에서, 자손의 멤버변수는 자손의 생성자에서 각각 초기화한다.
B는 apple, banana 두개의 멤버변수를 가지고 있다.
자손의 인스턴스를 생성하면 조상의 '디폴트로 매개변수 없는 생성자'가 호출된다
A(){...} 생성자가 선언딘 적이 없다. <- 에러가 났다
조상의 생성자가 먼저 생성됨
즉 자손쪽에서는 먼저 호출되는 조상의 생성자를 선택할 수 있다
선택하게 만드는 것에 super()test56.c
#include <stdio.h> #include <stdlib.h> typedef struct a { int apple; void (*print)(struct a*); }A; void a_print(A* this){ printf(" a_print(A* this->apple : %d\n",this->apple); } void a_constructor(A* this, int val){ this->apple = val; } void* new_a(int val){ A* t; t= (A*)malloc(sizeof(A)); t->print = a_print; a_constructor(t, val); return t; } typedef struct b { int apple; void (*print)(void *); int banana; }B; void b_print(void* self){ B *this; this = (B*)self; printf(" b_print(B* this->banana : %d\n",this->banana); } void b_constructor(void* self, int val){ B* this; this = (B*)self; this->banana = val; } void* new_b(int i, int j){ B* t; t= (B*)malloc(sizeof(B)); t->print = a_print; t->print = b_print; a_constructor(t,j); b_constructor(t,i); return t; } int main(){ A *a; a=(A*)new_a(200); a->print(a); B *b; b=(B*)new_b(100,200); b->print(b); free(a); free(b); return 0; }test59.java
abstract class A{ abstract void print(); void print2(){} //abstarct 하지 않은 함수를 같이 쓰는 건 상관없다 } class B extends A{ void print(){ System.out.println("print"); } void sound(){ System.out.println("sound"); } } public class test59{ public static void main(String[] args){ B banana = new B(); banana.print(); banana.sound(); } } /* print sound void print(); 로 함수 선언을 하려면 반드시 abstract가 앞에 붙어주어야한다 abstract 멤버함수를 하나라도 가지고 있는 클래스는 abstract 해야한다. abstract class는 인스턴스를 못 만든다 abstarct클래스 :: 추상클래스 인스턴스를 생성할 수 없는 클래스 하나이상의 추상메서드(구현되지 않은 메서드)를 가질 수 있음 자식클래스가 이 클래스를 상속받아 구현을 완성해야함 */test60.java
abstract class shoppingmall{ abstract int db(); void list(){ int result = db(); System.out.println(result); } } class shoppingmall_mysql extends shoppingmall{ int db(){ System.out.println("mysql 연동"); return 100; } } class shoppingmall_mariadb extends shoppingmall{ int db(){ System.out.println("mariadb 연동"); return 200; } } public class test60{ public static void main(String[] args){ shoppingmall D1 = new shoppingmall_mysql(); D1.list(); shoppingmall D2 = new shoppingmall_mariadb(); D2.list(); } } /* */현재 상황에서 결정할 수 없거나, 앞으로 변경이 만이 일어날 부분을 abstract로 비워놓고
변경이 적은 부분을 미리 클래스로 만들어놓을 수 있다
쇼핑몰 클래스의 재홀용 빈도가 늘어나게되고 -> 생산성이 향상된다
abstract method의 실체는 구조체 안의 함수포인터에 NULL값이 들어가 있는 꼴이다.
이러한 구조체는 MALLOC하게되면 폭탄이 될 수 있다. -> NULL 값이 들어간
함수포인터는 호출하면 터진다. -> 따라서 이런 구조체는 malloc못하게 해야 한다.
-> 인스턴스를 못 만다는 클래스
mysql 연동
100
mariadb 연동
200[교육 4일차]
test65.java
abstract class Apple{ abstract int add(int i, int j); } class Apple2 extends Apple{ int add(int i, int j){ return i+j; } } public class test65{ public static void main(String[] args){ Apple a = new Apple2(); System.out.println(a.add(1,2)); } } /* */선언되었지만 정의되지 않은 함수 : abstract method
(함수 포인터에 null 값이 대입된 형태와 유사)
함수 포인터에 null값이 대입된 구조체는 존재해서는 안된다. :: 언제 뻗을지 모른다
- 해서 java에서는 인스턴스를 못 만들게 문법으로 박았다 -> abstract class
abstract method 를 상속받으면서 오버라이딩을 하면 abstract 성격이 빠져나간다
t->add = NULL;test67.java
abstract class Clac { abstract int multicas(int i, int j); //Addclc(int a) {seed = a;} int execute (int i ) {return i + this.seed;} } class Mulcalc extends Clac{ int banana = 0; Mulcalc (int a ) {this.banana= a;} int execute (int i ) {return (banana+10)* i;} } public class test67{ public static void main(String[] args){ /*Clac a = new AddCalc(100); System.out.println(a.execute(20));*/ Clac b = new MulCalc(100); System.out.println(b.execute(20)); } }test68.java
interface IA { //void print(){}; // 에러 void print(); } class A implements IA { void print(){ // 오버라이딩abstract class Clac { } public class test68{ public static void main(String[] args){ //new IA(); // 에러 IA t = null; System.out.println(); } } /* */interface
- abstract method만 선언이 가능하다
- 앞에 abstract 안 붙여도 자동으로 붙는다.
- 당연히 인스턴스 못만든다 ( 좀 이상한 클래스다)
- 인터페이스를 상속받아 클래스를 만들때는 implements를 이용한다.
(인터페이스를 상속받아 인터페이스를 만들 때 extends를 사용한다)
- 인터페이스를 상속받아 클래스 선언할 때는 인터페이스의 모든 함수를 오버라이딩 해야한다.test73.java
class Adam{ private int redBook = 100; public int subHouse = 200; protected int map = 300; // 상속자는 접근 가능한데, 포인터로는 접근 불가 void picnic(){ System.out.println(redBook); System.out.println(subHouse); } } class Brown extends Adam{ void give(){ //System.out.println(redBook);//error System.out.println(subHouse); System.out.println(map); } } class Jen extends Brown{ void give2(){ //System.out.println(redBook);//error System.out.println(subHouse); System.out.println(map); } } public class test73{ public static void main(String[] args){ Adam a = new Brown(); //System.out.println(a.redBook); // error // redBook has private access in Adam System.out.println(a.subHouse); System.out.println(a.map); //System.out.println(a.give2()); } } /* */멤버변수와 멤버함수 앞에서
private : 포인터를 통해 접근이 불가능
protected : 다른 패키지에 속한 클래스는 포인터로 접근 불가능.
public
이 붙어서 접근을 제한할 수 있다
아무것도 없는 경우는 friendly라고 하는데
같은 패키지는 public, 다른 패키지에게는 private로 동작한다test74.java
class A{ public String toString(){ return "Hello world"; } } public class test74{ public static void main(String[] args){ Object t = new A(); System.out.println(t.toString()); System.out.println((int)(10/3.0)); } } /* */아무 클래스로부터 상속받지 않으면 extends Object가 생략된다
Object는 내장되어 있는 클래스, '모든클래스의 조상이 된다'
toString()은 Object에서 선언되었고, 또한 물려받았다.
java클래스의 모든 인스턴스는 toString()함수를 가지고 잇다 -> Object는 모든 클래스의 조상
toString함수를 오버라이딩 하면 t.toString()호출 시 오버라이딩 된 함수가 호출된다[JAVA 자료형]
자료형 이름 = 초기값;
정수형 변수 선언에 쓰는 자료형 4가지 : byte(8bit) short(16bit) int(32bit) long(64bit)
일반적으로 40... 이렇게 값을 쓰면 32bit값인데 40L은 64bit 값이 된다
실수형 변수 선언에 쓰는 건 두가지 : float (32bit) double(64bit)
3.14F 32bit가지는 실수 3.14는 64bit값
boolean으로 선언된 변수
char
UTF-8은 1~4바이트 크기를 가지는 가변 길이 문자 체계이고
이것이 인터넷의 표준 인코딩 방법이 되고 있다
필요한 경우, 8859_1(아스키코드), Unicode, UTF-8을 전환하는 것이 필요할 수 있다
약->강한타입
byte < short < int < long(64bit) < float(32bit) < double(64bit)
long(64bit) < float(32bit) : long이 64인데도 float가 더 쎄다(?) 왜?
약한 타입에서 강한 타입으로는 자동 형변환이 가능하지만
강한 타입에서 약한 타입으로는 강제로만 형 변환이 가능하다 (c언어에서는 없다)
100이 그대로 들어갈까? 아니면 변환시켜 들어갈까? 변환시켜 들어감. double이 강타입으로 자동형변환
변수가 double이고 값이 int면? 변수가 원하는 형태에 맞게 형 변환을 하고 (100.0)으로 바꾸고 대입한다
3.14는 double형이다. double에 int
약->강타입 : 자동변환 o ex) double b = 100 ; // 100.0
강->약타입 : 자동변환 x ex) int a= 3.14; error // int에 double 못 넣어.test80.java
public class test80{ public static void main(String[] args){ String t = "helloworld"; System.out.println(t); System.out.println(t.length()); System.out.println(t.substring(2,5)); } } /* */t는 포인터일까요? String은 자료형 아니라 클래스이고, t는 포인터
"Helloworld"는 랎? 인스턴스? -> 인스턴스여야한다
String은 new를 이용하지 않고 인스턴스를 생성하는 유일한 클래스이다.
length()는 문자열 길이를 리턴하는 String의 멤버함수이다.
[교육 5일차]test
반응형