java 교육 5일
[교육 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