인터페이스 (interface)

상수형 필드(필드명 대문자)와 추상 메소드로만 구성된 추상 클래스의 변형체
클래스에 추상메소드를 포함시키는 구조보다는 메소드의 통일성을 부여하기 위해서 추상 메소드만 따로 모아 놓은 추상 클래스
인터페이스의 멤버는 반드시 public. 필드는 상속이 아닌 인터페이스 것이기 때문에 public으로 되어 있어야 사용 가능


[public] interface 인터페이스명

{

// 그냥 작성하여도 자동으로 static final이 됨

[public] static final 자료형 필드명 = 초기값;     // [ ] 안에 있는 건 선택!


// 추상 메소드

[public abstract] 반환형 메소드명([자료형 매개변수]);

}


상수형 필드는 자동으로 선언되어 있는 것이고, 추상 메소드는 후손이 꼭 만들어야 하는 것이다


- 사용
상속을 통해서 후손이 부모 인터페이스의 추상 메소드를 완성 시키는 방식 → interface를 상속할 때에는 implements라는 키워드 사용


클래스의 상속 : extends 부모클래스명(단일 상속)
인터페이스의 상속 : implements 인터페이스명 (다중상속 가능)


class 클래스명 extends 클래스명 implements 인터페이스명

{ }


class 클래스명 implements 인터페이스명1, 인터페이스명2, 인터페이스명3 ...    // 다중 선언 가능

{ }


interface 인터페이스명 extends 부모인터페이스명    // 인터페이스 간에도 상속이 가능

{ }



equals

객체와 객체가 같은 것인지를 비교하는 메소드
일반적으로 String에서는 문자열 자체를 비교하는 메소드라고 보면 된다


String [] name = new String[5];

name[0] = "홍길동";

name[1] = "김말똥";

name[2] = "고길똥";

name[3] = "똥똥똥";

name[4] = "김지똥";

Scanner sc = new Scanner(System.in);

System.out.print("검색할 이름 : ");

String tmp = sc.next();

for(int i=0;i<name.length;i++)

{

if(name[i].equals(tmp))

{

System.out.println(i + "번째 인덱스에 위치합니다.");

break;

}

}



CRUD (Create Read Update Delete)

입력, 출력, 수정, 삭제 기능을 구현


// Grade.java

package kh.java.point.model.vo;


public abstract class Grade {

private String name;

private String grade;

private int point;

public Grade() {}

public Grade(String name, String grade, int point)

{

this.name = name;

this.grade = grade;

this.point = point;

}

public void setName(String name) {this.name = name;}

public void setGrade(String grade) {this.grade = grade;}

public void setPoint(int point) {this.point = point;}

public String getName() {return name;}

public String getGrade() {return grade;}

public int getPoint() {return point;}

public abstract double getInterest();

}


// Silver.java

package kh.java.point.model.vo;


public class Silver extends Grade{

public Silver() {}

public Silver(String name, String grade, int point)

{

super(name, grade, point);

}


@Override

public double getInterest() {

return this.getPoint()*0.03;

}


}


// Gold.java

package kh.java.point.model.vo;


public class Gold extends Grade{

public Gold() {}

public Gold(String name, String grade, int point)

{

super(name, grade, point);

}


@Override

public double getInterest() {

return this.getPoint()*0.05;

}


}


// Vip.java

package kh.java.point.model.vo;


public class Vip extends Grade{

public Vip() {}

public Vip(String name, String grade, int point)

{

super(name, grade, point);

}


@Override

public double getInterest() {

return this.getPoint()*0.1;

}

}


// PntMgrInterface.java

package kh.java.point.controller;


public interface PntMgrInterface {

public void start();

public void insertData();

public void printData();

public void modifyData();

public void deleteData();

public int searchData();

}


// PntMgr.java

package kh.java.point.controller;


import java.util.Scanner;

import kh.java.point.model.vo.*;


public class PntMgr implements PntMgrInterface{

Scanner sc = new Scanner(System.in);

private Grade [] g = new Grade [20];

private int index = 0;

private String grade, name;

private int point;

public PntMgr() {}


@Override

public void start() {

while(true)

{

System.out.println("========== 회원 관리 시스템 ==========");

System.out.println("1. 회원 추가");

System.out.println("2. 회원 전체 출력");

System.out.println("3. 회원 수정");

System.out.println("4. 회원 삭제");

System.out.println("0. 프로그램 종료");

System.out.print("선택 : ");

int select = sc.nextInt();

switch(select)

{

case 1:

insertData();

break;

case 2:

printData();

break;

case 3:

modifyData();

break;

case 4:

deleteData();

break;

case 0:

System.out.println("프로그램을 종료합니다");

return;

}

}

}


@Override

public void insertData() {

// 정보 입력시 1명씩 입력 및 추가 될 수 있도록 해야 함

System.out.println("======= 회원 추가 서비스 =======");

System.out.print("등급 입력 (Silver/Gold/Vip) : ");

grade = sc.next();

if(!(grade.equals("Silver") || grade.equals("Gold") || grade.equals("Vip")))

{

System.out.println("잘못 입력하셨습니다.(회원 추가를 종료합니다)");

return;

}

System.out.print("이름 입력 : ");

name = sc.next();

System.out.print("포인트 입력 : ");

point = sc.nextInt();

System.out.println("회원 추가가 완료되었습니다.");

if(grade.equals("Silver"))

{

g[index++] = new Silver(name,grade,point);

}

else if(grade.equals("Gold"))

{

g[index++] = new Gold(name,grade,point);

}

else if(grade.equals("Vip"))

{

g[index++] = new Vip(name,grade,point);

}

}


@Override

public void printData() {

// 정보 출력시 전체 출력

System.out.println("<<========== information ==========>>");

System.out.printf("%-15s %-15s %-15s %-15s \n","이름","등급","포인트","이자포인트");

for(int i=0;i<index;i++)

{

System.out.printf("%-8s %-8s %-10d %.1f \n", g[i].getName(),g[i].getGrade(),g[i].getPoint(),g[i].getInterest());

}

}


@Override

public void modifyData() {

// 정보 수정시 이름으로 검색하고 정보 수정이 가능 해야 함 - 검색은 searchData

int tmp = searchData();

System.out.print("수정될 등급 입력(Silver/Gold/Vip) : ");

grade = sc.next();

System.out.print("수정될 이름 입력 : ");

name = sc.next();

System.out.print("수정될 점수 입력 : ");

point = sc.nextInt();

System.out.println("수정이 완료되었습니다.");

if(grade.equals("Silver"))

{

g[tmp] = new Silver(name,grade,point);

}

else if(grade.equals("Gold"))

{

g[tmp] = new Gold(name,grade,point);

}

else if(grade.equals("Vip"))

{

g[tmp] = new Vip(name,grade,point);

}

}


@Override

public void deleteData() {

// 정보 삭제시 이름으로 검색하고 정보 삭제가 되어야 함 - 검색은 searchData

int tmp = searchData();

System.out.println("회원 정보가 삭제되었습니다.");

for(int i=0;i<index;i++)

{

if(g[i].getName() == g[tmp].getName())

{

g[i] = g[i+1];

}

}

index--;

}


@Override

public int searchData() {

System.out.print("검색될 회원 이름 입력 : ");

name = sc.next();

for(int i=0;i<index;i++)

{

if(g[i].getName().equals(name))

{

return i;

}

}


return -1;

}

}


TestMain.java

package kh.java.point.run;


import kh.java.point.controller.PntMgr;


public class TestMain {

public static void main(String[] args) {

new PntMgr().start();

}

}


  1. 좋아요 2018.03.29 14:43 신고

    좋아요

  2. 2018.05.23 10:36

    비밀댓글입니다

  3. 민호 2018.07.17 17:19 신고

    한 수 배우고 갑니당^^

  4. 디벨로퍼수 2018.08.17 11:49 신고

    김미경..

  5. 디벨로퍼수 2018.08.17 12:29 신고

    따라다니지 마세요 김미경님..

상속

A is a B : A 는 B 다 - A는 B를 상속받아 결국 A는 B의 것을 가지게 된다
객체지향 프로그래밍에서는 상속이라는 개념 사용


상속 받은 필드가 private 이라면?
자식 클래스에서는 상속 받은 필드가 private 되어 있으면 직접적인 접근은 불가능하나,
상속 받은 필드에 접근하기 필요성이 있을때에는 크게 3가지 방법을 통해 접근할 수 있다


1. 필드는 private으로 선언하지 않고 protected로 선언
2. 부모의 setter를 이용
3. 자식 생성자에서 사용할 수 있는 super 키워드로 부모 생성자 호출


다형성

상속을 이용한 기술로 상속 관계에 있는 부모, 자식 클래스 간에 부모 타입은 모든 후손 타입을 받아 줄 수 있다
부모 클래스 타입의 레퍼런스가 후손 객체의 주소를 저장할 수 있다는 뜻 (후손 객체 안에 부모 멤버가 포함되어 있기 때문에 가능)
부모 레퍼런스를 통해 객체의 접근시 부모가 가지고 있는 메소드만 사용 가능 (부모레퍼런스이지만 자식의 메소드를 호출하려면 다운캐스팅)


메소드 오버라이딩
부모 클래스의 메소드를 상속받지 않고 자신이 재정의 할때 사용하는 것
- Annotation (애너테이션, 어노테이션)
자바 소스코드에 추가하여 사용할 수 있는 메타데이터의 일종
'@' 기호를 붙여 사용하며 가상 머신에게 해당 문법에 대해 알려준다
메소드 오버라이딩시에는 @Override를 명시하여 오버라이드 된 메소드임을 JVM에게 알려준다 (생략하여도 자동으로 @Override가 명시)


abstract (추상화)
추상이라는 의미를 가지고 있는 키워드
메소드를 abstract로 만들경우 부모 클래스는 자신을 상속 받는 자식들에게 해당 메소드를 강제적으로 생성하라는 의미
(부모는 기능이 없는 메소드를 만든것이고 해당 기능을 가진 메소드를 자신을 상속 받은 자식들이 오버라이딩해서 정의하라는 의미)
abstract 메소드를 포함하고 있는 클래스는 불완전한 클래스 (기능이 없는 메소드를 가지고 있는 클래스가 객체화 되면 안된다)
그렇기 때문에 abstract 메소드를 포함하고 있는 클래스는 객체화 할 수 없도록 클래스 명 앞에 abstract 키워드를 붙여서 추상클래스로 선언 
(추상 클래스는 객체화 할 수 없는 클래스를 의미)


추상 클래스 (미완성된 클래스) : 객체 생성을 막아놓은 클래스 (추상 메소드가 없어도 명시할 수 있다)


public abstract class 클래스명 { }


클래스 안에 추상 메소드를 가지고 있으면 해당 클래스는 반드시 추상 클래스가 되어야 한다
추상 클래스를 상속받은 후손 클래스는 반드시 부모의 추상 메소드를 완성시켜야 하는 강제성이 부여되어,
후손은 추상 메소드를 반드시 오버라이딩 해서 선언 해두어야 한다


추상 메소드 (미완성된 메소드) : 메소드의 헤드(Head)만 있고, 몸체(Body : 내용)가 없는 메소드


public abstract 반환자료형 메소드명([자료형 매개변수]);


표준화된 인터페이스를 제공할 목적으로 추상메소드를 사용한다
메소드 사용의 통일성을 확보하고 메소드 제작을 강제화 한다



문제. 급여관리 시스템 제작하기

요구사항

1. has a 포함관계 is a 상속관계를 구현할것 !

2. VO 클래스와 controller 클래스를 나눌것 !

3. 확장성을 고려할것 ! (다형성)

4. 첫번째 VO 클래스 이름 : Permanent (정규직) - kh.java.pay.model.vo

5. Permanent 의 멤버필드 : 이름 , 분류, 급여 (3가지)

6. 멤버메소드 : setter, getter, 생성자 

7. 두번째 VO 클래스 이름 : PartTime (시간직) - kh.java.pay.model.vo

8. Parttime 의 멤버필드 : 이름 , 분류 , 시급, 일한시간 (4가지)

9. 자식 클래스들의 멤버메소드 : setter, getter, 생성자 , 급여getter 추가로 만들어야함

10. controller 클래스  이름 : PayMgr (급여매니저) - kh.java.pay.controller

11. Paymgr 의 멤버필드 : 직원10명관리할수 있는 객체 배열!!, 인덱스 

12 Paymgr 의 멤버메소드 : insertData, printData, 생성자 

13. 실행형 클래스에서 아래와 같이 실행 - kh.java.pay.run.TestMain

PayMgr p = new PayMgr();

p.insertData(new Permanent("홍길동","정규직",2000000));

p.insertData(new PartTime("김말똥","시간직",6000,200));

< < = = = = = = 출력결과 = = = = = = = > >

이름 분류 급여

길똥이 정규직 2000000

개똥이 시간직 1200000

만족 할때쯤 점검 !! 인턴직을 추가 해본다. 그때 컨트롤 클래스에 손이 가면 

다형성이 실패한것이다. (인터직은 급여 * 80 % )  

멤버변수는 정규직과 같다. 다만 급여*80%

p.insertData(new intern("김인턴","인턴직",2000000); // 김인턴 인턴직 1600000  이 출력


PayMgr p = new PayMgr();

p.insertData(new Permanent("홍길동","정규직",2000000));

p.insertData(new PartTime("김말똥","시간직",6000,120));

p.insertData(new Intern("삼국지","인턴직",2000000));

p.printData();


Permanent, PartTime, Intern의 부모 클래스

package kh.java.pay.model.vo;


public abstract class Job {

private String name;

private String job;

public Job() {}

public Job(String name, String job

{

this.name = name;

this.job = job;

}

public void setName(String name) {this.name = name;}

public void setJob(String job) {this.job = job;}

public String getName() {return name;}

public String getJob() {return job;}

public abstract int getPay();

}


Permanent.java

package kh.java.pay.model.vo;


public class Permanent extends Job{

private int pay;

public Permanent() {}

public Permanent(String name, String job,int pay)

{

super(name,job);

this.pay = pay;

}

@Override

public int getPay() 

{

return pay;

}

}


PartTime.java

package kh.java.pay.model.vo;


public class PartTime extends Job{

private int payHour;

private int payWork;

public PartTime() {}

public PartTime(String name, String job, int payHour, int payWork)

{

super(name,job);

this.payHour = payHour;

this.payWork = payWork;

}

@Override

public int getPay() {

return payHour * payWork;

}

}


Intern.java

package kh.java.pay.model.vo;


public class Intern extends Job{

private int pay;

public Intern() {}

public Intern(String name, String job, int pay)

{

super(name, job);

this.pay = pay;

}

@Override

public int getPay() {

return (int)(pay*0.8);

}

}


PayMgr.java

package kh.java.pay.controller;


import kh.java.pay.model.vo.*;


public class PayMgr {

private Job [] j = new Job [10];

private int index = 0;

public PayMgr() {}

public void insertData(Job j)

{

this.j[index++] = j;

}

public void printData()

{

System.out.println("<<====== 출력결과 ======>>");

System.out.printf("%-15s %-15s %-15s \n", "이름","분류","급여");

for(int i=0;i<index;i++)

{

System.out.printf("%-13s %-13s %-15d \n", j[i].getName(),j[i].getJob(),j[i].getPay());

}

}

}


TestMain.java

package kh.java.pay.run;


import kh.java.pay.controller.PayMgr;

import kh.java.pay.model.vo.*;


public class TestMain {

public static void main(String[] args) {

PayMgr p = new PayMgr();

p.insertData(new Permanent("홍길동","정규직",2000000));

p.insertData(new PartTime("김말똥","시간직",6000,200));

p.insertData(new Intern("삼국지","인턴직",2000000));

p.printData();

}

}



문제

다음 실행용 클래스에서 아래와 같이 코딩시 컨트롤 클래스에서 처리할 수 있도록 만들어 보시오

public class TestMain{     //실행용 클래스

public static void main(String[] args) {

StuMgr m = new StuMgr();

m.insertStudent(new Student("홍길동",20,"경기도"));

m.insertStudent(new Student("김말똥",30,"충청도"));

m.insertStudent(new Student("고길똥",99,"서울시"));

m.viewAllStudent();     //저장된 모든 학생들 정보 출력

}

}

조건
1. Student Class는 VO Class 임 (패키지명 : kh.java.model.vo)
## 필수 ##
- 멤버변수 : 이름,나이,주소
- 멤버메소드 :setter, getter, 기본생성자
2. StuMgr Class는 Controller Class임 (패키지명 : kh.java.controller)
## 필수 ##
- 멤버변수 : 학생정보 10명을 저장할 수 있는 객체 배열
- 멤버메소드 : insertStudent (객체 저장 메소드), viewAllStudent (정보 출력 메소드)
3. Has a 포함관계로 구현할 것 (Stumgr -> Student)
4. 학생 10명에 대한 정보를 저장할 수 있어야 함
5. 실행용 클래스는 TestMain (패지키명 : kh.java.run)
출력 결과 (viewAllStudent 메소드 호출시) - 줄칸은 맞지 않아도 됩니다.
= = = = = = = = = = = 학생 정보 출력 = = = = = = = = =
이름 나이        주소
      홍길동   20       경기도
      김말똥   20       충청도
      고길똥   99       서울시


has a 설계
패키지
kh.java.model.vo
-> 클래스 : Student
- 멤버변수 : 이름,나이,주소
- 멤버메소드 :setter, getter, 기본생성자
kh.java.controller
-> 클래스 : StuMgr
- 멤버변수 : 학생정보 10명을 저장할 수 있는 객체 배열
- 멤버메소드 : insertStudent (객체 저장 메소드), viewAllStudent (정보 출력 메소드)
kh.java.run
-> 클래스 : TestMain
- 멤버메소드 : main 


Student.java

package kh.java.model.vo;


public class Student {

private String name;

private int age;

private String addr;

public Student(){}

public Student(String name, int age, String addr)

{

this.name = name;

this.age = age;

this.addr = addr;

}


public void setName(String name) {this.name = name;}

public void setAge(int age) {this.age = age;}

public void setAddr(String addr) {this.addr = addr;}

public String getName() {return name;}

public int getAge() {return age;}

public String getAddr() {return addr;}

}


StuMgr.java

package kh.java.controller;


import kh.java.model.vo.Student;


public class StuMgr {

private Student [] s = new Student [10];

private int index = 0;

public void insertStudent(Student s)

{

this.s[index++] = s;

}

public void viewAllStudent()

{

System.out.println("========== 학생 정보 출력 ==========");

System.out.printf("%15s %15s %15s \n", "이름","나이","주소");

for(int i=0;i<index;i++)

{

System.out.printf("%15s %14d %8s \n", s[i].getName(),s[i].getAge(),s[i].getAddr());

}

}

}


TestMain.java

package kh.java.run;


import kh.java.controller.StuMgr;

import kh.java.model.vo.Student;


public class TestMain {

public static void main(String[] args) {

StuMgr m = new StuMgr();

m.insertStudent(new Student("홍길동",20,"경기도"));

m.insertStudent(new Student("김말똥",30,"충청도"));

m.insertStudent(new Student("고길똥",99,"서울시"));

m.viewAllStudent();

}

}




클래스 다이어그램

클래스(멤버변수-필드, 메소드)를 그림으로 표현



Help - Install New Software



Location에



objectaid.com/download
Download URL 주소를 적는다.



ObjectAid UML Explorer에서 Apache Batik과 ObjectAid Class Diagram만 체크하고 Next, Next ..



I accept the terms of the license agreements를 체크하고 Finish
Security Warning 창이 뜨면 'Install anyway', Software Updates 창이 뜨면 Restart Now



File - New - Other 에서 ObjectAid Class Diagram을 찾아서 패키지에 추가한다



다이어그램에 표시하고 싶은 클래스들을 끌어다 놓으면 요렇게 그려진다


  1. ㅇㅇㅇ 2018.03.29 14:41 신고

    자바 정말 잘하시네용~

객체지향 프로그래밍

현실 세계는 사물이나 개념처럼 독립되고 구분되는 각각의 객체로 이루어져 있다
각각의 독립되는 형태로 구현되어 있는 것이 객체이고 이 개념을 바탕으로 프로그래밍을 하는 것을 객체지향 프로그래밍

- 객체지향 언어는 객체지향 프로그래밍을 하기 위해 만들어진 언어

프로그램 객체를 만들기 위해서는 실제 객체에 대한 분석이 필요

객체(Instance)를 표현하는 것에는 속성(데이터)와 기능(메소드)을 가지고 있다


객체지향 용어
클래스 : 객체를 만들기 위한 설계도 혹은 틀. 사물이나 개념의 공통요소(속성, 기능)을 용도에 맞게 추상화
추상화(abstraction)
- 프로그램에서 필요한 속성과 기능을 추출하고 불필요한 것을 제거하는 과정
- 프로그래밍적으로 보았을 때 속성(변수)으로 사용할 것과 기능(메소드)으로 구현할 것들을 설계하는 과정


객체지향 프로그래밍 단계 : 대상 물색 → 추상화 → 설계 (클래스 작성) → 사용 (인스턴스화)


변수 : 데이터를 저장하는 공간
배열 : 데이터를 연속적으로 저장하는 공간 (같은 타)
구조체 : 여러 데이터 타입의 데이터를 저장하는 공간


클래스 선언

[접근제어지시자] [예약어] class 클래스명

{

// 속성

[접근제어지시자] 자료형 변수명;

[접근제어지시자] 자료형 변수명;


// 기능

[접근제어지시자] [예약어] 리턴형 메소드명 ( )

{

// 기능정의

}

}


접근제어 지시자 : 클래스 안에서 변수 및 메소드 생성시 접근제어 지시자를 사용. 접근할 때 허용하는 범위를 말하는 것
- public : 어디서든 접근 허용
- protected : 후손클래스(상속), 같은 패키지 내, 해당클래스 내부에서 접근 가능
- default : 같은 패키지 내, 해당클래스 내부에서 접근 가능

접근제어 지시자를 작성하지 않으면 default로 설정

- private : 해당 클래스에서만 접근 가능


원칙
클래스 안의 멤버 변수는 private으로 설정하는 것을 원칙 (멤버 변수는 데이터를 저장하고 있는 중요한 공간이기 때문에 보호)
클래스 안의 멤버 메소드는 다양하게 사용할 수 있다 (기본은 public)



객체지향 3대 원칙 : 캡슐화, 상속, 다형성


캡슐화

하나의 객체는 독립적으로 완벽한 역할을 수행할 수 있어야 한다
정보은닉 + 독립적인 역할을 캡슐화 작업을 하였다 라고 볼 수 있다 - 실제 내부 코드를 보지 않고도 사용자는 사용할 수 있어야 한다


정보은닉 : 정보를 숨기는 것
- 클래스의 멤버 변수는 일반적으로 private 영역에 저장하여 의도치 않은 외부 접근에 대한 오류를 방지
- 클래스를 만든 개발자는 해당 클래스의 멤버 변수를 타 사용자가 마음대로 바꾸게 두어서는 안 됨 (흐름의 문제가 발생)


변수의 종류
- 지역변수 : 해당 메소드 안에서만 사용가능. 메소드가 호출될 때 생성되고 메소드가 종료될 때 삭제. Stack에 생성
- 전역변수 : 해당 클래스 안에서 사용가능 (객체 생성시 해당 객체만). 객체가 생성될 때 생성되고 객체가 소멸할 때 삭제. Heap에 생성
- 정적변수 : private으로 생성시 실제 생성된 객체끼리 공유, public으로 생성시 어디서든 사용가능. 프로그램 시작/종료. Static에 생성


public class Test{

private static int staticVal;    // 정적변수 (클래스변수)

private int globalVal;          // 전역변수 (멤버변수)

public void local(){

int localVal;                // 지역변수

}


}


final 키워드 : 상수화 시키는 키워드. 변수 데이터 타입 앞에 final 키워드를 붙이면 상수화 시키겠다 라는 의미
final 변수는 명명규칙에 의하여 대문자를 사용


int a = 10;          // 10을 담고 있는 a라는 변수

final int a = 10;    // 10을 담고 있는 a라는 상수


static을 명시하면서 final 키워드를 붙이게 되면 어디서든 사용가능한 상수 라는 의미


public static final int RED = 0xFF0000;    // final 변수는 명명규칙에 의하여 대문자를 사용


메소드에 사용되는 static 키워드 와 final 키워드
- 메소드에 static 키워드를 붙이게 되면 객체의 메소드가 아닌 클래스의 메소드. 따로 객체를 만들고 사용하지 않아도 된다 (즉석 사용 가능)
- 메소드에 final 키워드를 붙이게 되면 메소드 오버라이딩을 막겠다는 의미
- 클래스에 final 키워드를 붙이게 되면 상속을 막겠다는 의미


getter 메소드와 setter 메소드
클래스를 개발할 때 멤버변수의 값을 넣거나 혹은 꺼낼 수 있는 메소드를 만들 때에는 get과 set을 메소드명에 붙여서 제작


this 키워드 : 해당 클래스 안에 존재하는 멤버변수를 표현할 때에는 this라는 키워드를 사용하여 자기 자신을 지칭. 해당 객체의 주소값을 담고 있다


// Setter 메소드 : 필드에 변경할 값을 전달 받아서 필드값을 변경하는 메소드

접근제한자 void set필드명(자료형 변수)

{

this.필드명 = 자료형 변수;

}


// Getter 메소드 : 필드에 기록된 값을 읽어서 요구하는 쪽으로 읽은 값을 넘기는 메소드

접근제한자 반환형 get필드명( )

{

return 필드명;

}


private String name;    // name이라는 멤버변수


public void setName(String name)    // 멤버변수와 매개변수의 이름이 동일한 경우 가장 가까운 변수를 지목한다

{

this.name = name;

}

public String getName( )

{

return name;

}


생성자와 소멸자
생성자는 class를 바탕으로 객체가 생성될 때 자동으로 호출되는 메소드

- 일반적으로 객체가 제대로 동작할 수 있게 준비하는 역할 (기본 데이터 입력)
- 메소드 이름은 클래스 이름과 같아야 하며 턴 값은 존재하지 않는다 (리턴 데이터 타입도 명시하지 않는다)
- 주의할 점 : 생성자 코드를 수정하게 되면 디폴트(기본) 생성자(매개변수가 존재하지 않는 생성자)가 없어지게 된다
- 일반 메소드와 마찬가지로 오버로딩이 가능


→ 메소드 오버로딩
메소드 호출시 메소드명과 매개변수 개수, 타입을 보고 호출할 메소드를 찾으므로,
같은 이름의 메소드명이라고 하더라도 매개변수의 개수가 다르거나 타입이 다르다면 동일한 메소드명으로 제작이 가능


class 클래스명

{

[접근제어지시자] 클래스명( ) {  }    // 기본 생성자 - 코드 꼭 추가

[접근제어지시자] 클래스명(매개변수)

{

(this.)필드명 = 매개변수;

}

}


소멸자는 객체가 소멸할 때 자동으로 호출되는 메소드 - 타 언어에서는 존재하지만 '자바'에서는 존재하지 않는다

- 존재하지 않는 이유
타 언어(c++)에서는 사용한 메모리에 대한 정리도 개발자가 직접 해야 한다. (new를 사용하면 사용한 객체를 지울 때는 delete를 코딩)
'자바'라는 언어는 메모리에 대한 정리는 개발자가 하지 않고 JVM이 직접 관리 하도록 하기 위하여 GC(Garbage Collector)가 존재
GC는 JVM에서 사용하는 메모리가 꽉차기 전에 자동으로 특정 알고리즘에 의해서 메모리 정리 역할을 한다
즉, 자바는 개발자에게 메모리 관리까지 생각하여 코딩하지 말고 프로그램 개발에만 집중할 수 있도록 만든 개발자 중심의 언어


has a 포함 관계 - A has a B : A 안에는 B가 포함되어 있다
자바에서 포함이란 재활용하고 싶은 클래스의 객체를 멤버변수로 선언하는 방법 - A 클래스 안에 B 클래스를 멤버 변수로 사용하겠다
자바에서는 데이터를 표현하는 클래스와 해당 데이터를 운영하는 클래스를 별도로 두고 있다.

- 데이터가 되는 클래스 : Entity, VO, DTO - 순수 데이터를 표현
- 데이터를 컨트롤 하는 클래스 : Controller - 데이터를 운영


public Student    // 데이터가 되는 클래스 (Entity 또는 VO 또는 DTO 라고 부름)

{

private String name;

public void setName(String name){ this.name = name; }

public String getName(){ return this.name; }

}


public StuMgr    // Controller - 데이터를 운영하는 클래스

{

private Student s;

}


객체배열

Student [ ] stdArr = new Student[3]; // 레퍼런스 배열 생성 : 객체를 생성할 때 new 라는 연산자를 사용하여 생성

stdArr[0] = new Student();         // 각 레퍼런스 마다 new라는 연산자를 사용하여 객체를 생성함

stdArr[1] = new Student();         // 각 레퍼런스 마다 new라는 연산자를 사용하여 객체를 생성함

stdArr[2] = new Student();         // 각 레퍼런스 마다 new라는 연산자를 사용하여 객체를 생성함


→ Student [ ] stdArr = new Student[3]는
실제 객체들에 대한 배열을 만드는 것이 아닌 레퍼런스의 배열을 생성하는 것이므로 레퍼런스마다의 객체는 별도로 생성 해주어야 한다


String [] args

main 메소드에 있는 매개변수 중 문자열 배열을 의미
main 메소드에도 매개변수가 있다면 호출할 때 인자값을 넘겨줄 수 있다는 의미


인자값의 데이터 형태
String 배열로 넘어오기 때문에 모든 데이터는 문자열 형태로 넘어온다
문자열로 넘어온 데이터를 정수로 변경하여 사용하려면 Integer.parseInt 메소드를 사용

- 실수 변환은 Double.parsedouble

데이터는 띄어쓰기를 구분자로 확인하여 각각 args 인덱스에 들어간다


main 메소드 호출
일반 메소드는 개발자에 의해서 호출된다면, main 메소드는 프로그램을 시작하게 되면 JVM이 main 메소드를 찾게 되고 호출
프로그램 시작 전 main에 보내줄 인자 값을 작성하게 되면 main을 호출할 때 main에서 해당 인자값을 가져다 사용


public static void main(String[] args

{

String cal = args[1];

switch(cal)

{

case "+":

System.out.println(Integer.parseInt(args[0]) + Integer.parseInt(args[2]));

break;

case "-":

System.out.println(Integer.parseInt(args[0]) - Integer.parseInt(args[2]));

break;

case "x":

System.out.println(Integer.parseInt(args[0]) * Integer.parseInt(args[2]));

break;

case "/":

System.out.printf("%.2f",Double.parseDouble(args[0]) / Double.parseDouble(args[2]));

break;

}

}



이클립스 이용방법



Run - Run Configrations - Arguments - Program arguments에 인자값을 넣어주고 Apply - Run



exe 파일 만들어서 cmd 창 이용 방법



Export - Runnable JAR file을 선택하고 Next 후 해당 자바 파일을 선택하고 jar 파일명을 지정했다면 Finish



launch4j.sourceforge.net
Download를 클릭하여 해당 파일을 찾아서 설치한다



Basic 설정 : Output file은 파일명.exe 경로 지정, Jar는 아까 만든 jar 파일의 경로를 찾아서 지정한다



Classpath 설정 : Custom classpath를 체크하고, Main class는 jar 파일을 선택하여 정한다



Header 설정 : Header type은 Console을 선택한다



JRE 설정 : Min JRE version을 1.6.0으로 한다



톱니바퀴로 .xml 파일을 만든 후 cmd창에 exe 파일을 끌어다놓아서 경로를 자동 지정하고 인자값들을 넣어주면



다음과 같은 결과가 나온다


minimelody.tistory.com/130


메소드 (Method)

타 언어에서는 함수(function), 기존에 작성하던 공간(main 및 기타 메소드)도 하나의 메소드
기능별 구분이 가능해지고 재사용하는 코드들을 메소드로 정의하여 중복 코드 제거
메소드명은 해당 기능명을 작성하는게 원칙, 낙타표기법


- 형태

[접근제어지시자] [예약어] 반환형 메소드명 (매개변수)    // 예약어 : static, final, abstract, syncronized, static final(final static)

{

메소드 실행 코드

return 값;

}


작성 Tip : 기본틀 작성 → 메소드명 수정 → 매개변수 수정 → 실행 코드 수정 → 리턴 데이터 타입 수정
Caller(호출 한 메소드), Callee(호출 당한 메소드)


public int sum (int a, int b)

{

int c;

c = a + b;

return c;

}


public : 접근 제어 지시자
int : 리턴 데이터 타입 (반환 형태 - 반환하는 값의 데이터 타입)

- 리턴값이 있을 경우 리턴 데이터 타입이 명확
- 리턴값이 없을 경우 void 형을 사용

sum : 메소드 명 (호출시 필요한 메소드 이름)
(int a, int b) : 매개변수 (Parameter) → 호출시 보낸값 (인자 혹은 인수(argument))을 저장하는 변수

- 매개변수가 없을 경우 매개변수 부분을 비워놓는다 → public int sum ( )

{ 코드; } : 해당 메소드 호출시 실행하는 코드
return c; : 호출이 끝나면 돌아갈때 가져가는 값 → 리턴값이 있을 경우 리턴 데이터 타입이 명확해야 한다


- 구분
전달인자(argument)와 반환값(return value)의 유무에 따라 4가지로 구분


1. 전달인자(O), 반환값(O)

public int sum(int su1, int su2)

{

return su1+su2;

}


2. 전달인자(O), 반환값(X)

public void printValue(int a)

{

System.out.println(a);

}


3. 전달인자(X), 반환값(O)

public int inputValue()

{

Scanner sc = new Scanner(System.in);

int a = sc.nextInt();

return a;

}


4. 전달인자(X), 반환값(X)

public void onlyPrint()

{

System.out.println("수고하셨습니다.");

}


- 메모리 처리
메소드 안에서 생성되는 변수들은 해당 메소드에서만 사용이 가능 → 해당 메소드에서만 사용하기 때문에 이름 중복 문제가 발생하지 않는다


- 호출 방식
호출할 때 인수(혹은 인자)를 전달하는 방식
값에 의한 호출 (Call By Value) : 인수의 값을 호출한 메소드에 전달, 원본 값 수정 불가
참조에 의한 호출 (Call By Reference) : 인수의 주소를 호출한 메소드에 전달, 원본 값 수정 가능


public static void main(String[] args) {

Scanner sc = new Scanner(System.in);


System.out.println("입력(1~100)");

int num = sc.nextInt();

if(1<=num && num<=100)

{

System.out.println("출력");

printData(num);

}

}


public static void printData(int num) {

int [][] arr = new int [num][num];

for(int j=0;j<num;j++)

{

for(int i=0;i<num;i++)

{

arr[j][i] = (j+1)*(i+1);

System.out.printf("%-5d", arr[j][i]);

}

System.out.println();

}

}



메모리 구조
Stack : 일반 변수나 레퍼런스 변수 생성

레퍼런스 변수 : 주소를 저장하는 변수

Heap : New 연산자 사용시 생성 (동적 메모리)
Static : 정적(Static) 변수나 메소드가 생성


배열

동일한 타입을 가지는 변수들의 집합. 여러 개의 변수를 한 번에 선언 가능

많은 양의 데이터를 저장하기 위해 사용


- 선언 : 주소값을 저장하기 위한 레퍼런스 변수가 필요 (Stack)

자료형 [ ] 변수이름 ;
자료형 변수이름 [ ] ;


- 할당 : 배열객체 생성 후 변수에 주소값 할당 (Heap)
변수이름 = new 자료형 [저장데이터개수];

- 초기화

int [ ] arr = {1,2,3,4,5};                  // 자동으로 배열을 생성하여 초기값을 넣고 생성

int [ ] arr = new int [ ] {1,2,3,4,5};    // new를 이용하여 배열을 생성하고 초기값을 넣음


int [ ] arr = new int [5] {1,2,3,4,5};    // 이것은 에러가 발생. 초기값을 넣을 때에는 배열의 길이 생략


초기값 없이 배열의 사이즈를 선언하지 않으면 사용할 수 없다.

버블정렬

int [ ] arr = new int [5];

for(int i=0; i<arr.length; i++)

{

System.out.print((i+1) + "번째 숫자 입력 : ");

arr[i] = sc.nextInt();

}

int tmp;

for(int j=0; j<arr.length-1; j++)

{

for(int i=0; i<arr.length-1; i++)

{

if(arr[i]>arr[i+1])

{

tmp = arr[i];

arr[i] = arr[i+1];

arr[i+1] = tmp;

}

}

}

for(int i=0; i<arr.length; i++)

{

System.out.print(arr[i] + "\t");

}



복사 : 값을 복사


배열 복사
얕은 복사 : 참조하고 있는 주소값만을 복사하여 사용 (같은 데이터를 참조하는 형태)


int [ ] arr1 = new int [4];

int [ ] arr2 = arr1;


깊은 복사 : 새로운 공간을 생성하여 기존 데이터값을 복사하여 넣음 (Heap에 새로운 데이터 생성)

System.arraycopy 메소드

System.arraycopy(src레퍼런스, src인덱스, dest레퍼런스, dest인덱스, 길이);

- src레퍼런스 : 복사할 대상 레퍼런스

- src인덱스 : 복사할 대상의 시작 인덱스 번호

- dest레퍼런스 : 저장될 목적지 레퍼런스

- dest인덱스 : 저장될 대상의 시작 인덱스 번호

- 길이 : 개수

clone 메소드


System.out.print("사용자의 전화번호 : ");

String str = sc.next();

char [] ch = new char [str.length()];

for(int i=0; i<str.length(); i++)

{

ch[i] = str.charAt(i);

}

char [] copy = new char [str.length()];

// System.arraycopy() 메소드 이용

System.arraycopy(ch, 0, copy, 0, str.length());

// clone() 메소드 이용

copy = ch.clone();

for(int i=4; i<8; i++)

{

copy[i] = '*';

}

System.out.println(copy);

System.out.println(ch);



로또

// 내 번호

int [] me = new int [6];

for(int i=0;i<6;i++)

{

System.out.print((i+1) + "번째 자리 숫자 : ");

me[i] = sc.nextInt();

}

System.out.println("내 번호");

for(int i=0;i<6;i++)

{

System.out.print(me[i] + " ");

}

System.out.println();

// 로또 번호

System.out.println("로또 번호");

int [] lotto = new int [6];

int tmp;

boolean chk = false;

while(true)

{

for(int j=0;j<6;j++)

{

tmp = r.nextInt(45)+1;

for(int i=0;i<6;i++)

{

if(lotto[i] == tmp)

{

chk = true;

}

}

if(chk==false)

{

lotto[j] = tmp;

}

else if(chk==true)

{

j--;

chk = false;

}

}

for(int j=0;j<5;j++) // 버블정렬

{

for(int i=0;i<5;i++)

{

if(lotto[i]>lotto[i+1])

{

tmp = lotto[i];

lotto[i] = lotto[i+1];

lotto[i+1] = tmp;

}

}

}


for(int i=0;i<6;i++)

{

System.out.print(lotto[i] + " ");

}

System.out.println();

// 내 번호 = 로또 번호

int count=0;

for(int j=0;j<6;j++)

{

for(int i=0;i<6;i++)

{

if(me[j] == lotto[i])

{

count++;

}

}

}

if(count==4)

{

System.out.println("3등!");

}

if(count==5)

{

System.out.println("2등!!");

}

if(count==6)

{

System.out.println("1등!!!");

break;

}

}



2차원 배열

2차원 배열은 인덱스를 2개 사용하여 행과 열을 표현

자료형 [ ] [ ] 변수이름;

자료형 변수이름 [ ] [ ];

자료형 [ ] [ ] 변수이름 = new 자료형 [행크기][열크기];


int [ ] [ ] arr = new int [행] [열]    // 가로가 행, 세로가 열

int [ ] [ ] arr = new int [3][4];       // 3개의 행과 4개의 열이 만들어 짐


초기화

int [ ] [ ] arr = {1,2,3,4,5,6,7,8};    // 2x4 4x2 인지 모르기 때문에 불가능

int [ ] [ ] arr = {{1,2,3,4}, {5,6,7,8}};


while(true)

{

System.out.print("가로행의 개수를 입력하세요(1~10) ==> ");

int width = sc.nextInt();

if(!(1<=width && width<=10))

{

System.out.println("반드시 1~10 사이의 정수를 입력해야 합니다.");

continue; // break이 반복문을 빠져나가는 구문이라면 continue는 반복문을 다시 실행한다.

}

System.out.print("세로열의 개수를 입력하세요(1~10) ==> ");

int height = sc.nextInt();

if(!(1<=height && height<=10))

{

System.out.println("반드시 1~10 사이의 정수를 입력해야 합니다.");

continue;

}

else 

{

int [][] alphabet = new int [width][height];

for(int j=0;j<height;j++)

{

for(int i=0;i<width;i++)

{

alphabet [i][j] = r.nextInt(26)+97;

System.out.print((char)alphabet [i][j] + " ");

}

System.out.println();

}

break;

}

}




가변 배열

2차원 배열 선언시 마지막 열 크기를 지정하지 않고, 추후에 지정함으로써 고정된 2차원 배열 크기가 아닌 유동적인 가변 배열을 구성


자료형 [ ] [ ] 변수이름 = new 자료형 [행길이] [ ];


int [ ] [ ] arr = new int [3][ ];

arr[0] = new int [3];

arr[1] = new int [2];

arr[2] = new int [5];


System.out.println("----- A 아파트 정보 입력 -----");

System.out.print("건물 총 층수 입력 : ");

int floor = sc.nextInt();

String [][] apart = new String[floor][];

System.out.println(floor + "층이 생성 되었습니다");

for(int i=0;i<apart.length;i++)  // 2차 배열 length

{

System.out.print((i+1) + "층의 총 호실 입력 : ");

apart[i] = new String [sc.nextInt()];

}

for(int i=0;i<apart.length;i++)

{

System.out.println((i+1) + "층은 " + apart[i].length + "호실까지 생성 되었습니다");

}

System.out.println("각 호실마다 입주자의 이름을 입력하세요");

for(int i=0;i<apart.length;i++)

{

System.out.printf("========== %d 층 정보 입력 ========== \n",i+1);

for(int j=0;j<apart[i].length;j++)

{

System.out.printf("%d층 %d호 입주자 : ",i+1,j+1);

apart[i][j] = sc.next();

}

}

System.out.println("------- 각 층 입주자 정보 -------");

for(int i=0;i<apart.length;i++)

{

System.out.print((i+1) + "층 : ");

for(int j=0;j<apart[i].length;j++)

{

System.out.print(apart[i][j] + " ");

}

System.out.println();

}


while

사용자가 원하는 만큼 명령들을 여러번 실행하는 제어 구조
특정 조건이 만족되는 동안 명령을 계속적으로 실행


while(조건문)

{

실행문;

}


int i=0;    // 초기

int sum=0;

while(i<5)    // 조건

{

i++;    // 증감

System.out.print("정수값을 입력하시오 : ");

int num = sc.nextInt();

sum += num;

}


System.out.println("입력한 5개의 정수의 합 : " + sum);




do - while

do와 while이 짝을 이루어 사용. 조건문이 실행문 뒤에 위치하여 1번 실행 후 조건을 물어본다

조건이 거짓일지라도 1번은 무조건 실행되는 제어문


do {

실행문;

}

while(조건문);


int num = 0;

do {

System.out.print("number? ");

num = sc.nextInt();

if(num > 0)

{

System.out.println("positive integer");

}

else if(num < 0)

{

System.out.println("negative number");

}

}

while(num != 0);

System.out.println("End");




for

가장 보편적인 반복문으로 다른 반복문에 비해 가독성이 높고 상대적으로 문법이 쉽다. 초기, 조건, 증감문을 한번에 선언하여 사용


for(초기; 조건; 증감)

{    

실행문;

}


int sum=0;

System.out.print("n의 수를 입력 : ");

int num = sc.nextInt();

for(int i=1; i<=num; i++)

{

if(i%2==0)

{

sum+=i;

}

}

System.out.println("짝수들만의 합은:" + sum);



중첩 for : for문 안에 for문이 들어간 형태로 내부의 명령을 외부의 횟수만큼 반복하게 되는 구조


for (초기값; 조건값; 증감값)

{

for (초기값; 조건값; 증감값)

{

실행코드;

}

}


System.out.print("입력 : ");

int input = sc.nextInt();

for(int j=1;j<=input;j++)

{

for(int i=0;i<j;i++)

{

System.out.print("*");

}

System.out.println();

}



int sum=0, i=0, num=0;

while(sum < 100)

{

i++;

if(i%2==1)

{

sum+=i;

num++;

}

else

{

sum-=i;

num++;

}

}


or


int num=1, sum=0;

for(int i=0; i<num; i++)

{

sum += (i%2==0) ? i*-1 : i ;

num++;

if(sum>=100)

{

num=i;

break;

}

}

System.out.println(num);




무한 루프

반복 횟수가 미리 정해져 있지 않고, 무한히 반복되는 루프 - while문을 많이 사용


for(;;)

{

실행문;

}


or


while(true)

{

실행문;

}


break : 반복문을 빠져나가는 구문
continue : 반복문을 다시 실행 (for문의 경우 증감식으로 이동)


while(true)

{

System.out.println("\n=== 계산기 프로그램 ===\n");

System.out.print("연산자 입력 (+, -, *, / (q:종료)) : ");

char op = sc.next().charAt(0);

if(op == 'q')

{

break;

}

System.out.print("첫 번째 숫자 입력 : ");

int num1 = sc.nextInt();

System.out.print("두 번째 숫자 입력 : ");

int num2 = sc.nextInt();

System.out.println("\n====== 결 과 ======\n");

switch(op)

{

case '+':

System.out.println(num1 + " + " + num2 + " = " + (num1+num2));

break;

case '-':

System.out.println(num1 + " - " + num2 + " = " + (num1-num2));

break;

case '*':

System.out.println(num1 + " * " + num2 + " = " + (num1*num2));

break;

case '/':

System.out.println(num1 + " / " + num2 + " = " + ((double)num1/num2));

break;

}

}




난수 (Random class)

임의의 값 또는 무작위로 만들어지는 알 수 없는 값


Random r = new Random( );

System.out.println(r.nextInt(100));    // 0~99 까지 중 임의의 수를 출력


Random r = new Random();


System.out.println("0 ~ 9 까지의 랜덤 수 : " + r.nextInt(10));

System.out.println("1 ~ 10 까지의 랜덤 수 : " + (r.nextInt(10)+1)); 

System.out.println("20 ~ 35 까지의 랜덤 수 : " + (r.nextInt(16)+20));

System.out.println("0 또는 1 : " + r.nextInt(2));



+ Recent posts