2주차
< 클래스와 객체(1) >
1.객체(Object) : 속성(필드) + 동작(메소드)로 구성
2.클래스 : 자바의 설계도
인스턴스(instance) : 클래스로부터 만들어진 객체
-new 클래스(); => new 연산자로 메모리 힙 영역에 객체 생성
-클래스 구성 멤버 : 필드, 생성자, 메소드
-필드 선언 => 초기값 지정되지 않은 필드는 객체 생성 시 자동으로 기본 초기값 설정(지역변수와 다르게)
3.생성자: 클래스로부터 new 연산자로 객체 생성 시 객체 초기화 담당. 리턴 타입 x, 클래스 이름과 동일
- 생상자 명시적으로 선언 가능, 선언하면 기본생성자 생성 x, 반드시 선언된 생성자 호출하여 객체 생성
- 매개 변수 이름 필드 이름과 유사,동일 권장 but 완전히 동일할 경우 this.필드 쓰기
- 생성자 오버로딩: 매개변수 타입이나 개수가 달라야함
- 다른 생성자 호출 : this()
4.메소드 : return 값 있는 경우 리턴 타입 선언부에 명시
- 메소드 오버로딩 : 조건은 매개 변수의 타입이나 개수가 달라야함. 매개 변수 같고 리턴 타입 다른 경우 오버로딩 성립 x
[ 실습문제 ]
학생클래스 선언
=> 필드: 국적, 이름, 나이, 학과
=> 각 필드에 대한 접근자/변경자 메소드 정의
=> 생성자 오버로딩
Student.java
class Student{
//필드 선언
//메소드 선언
string nation, age, major;
int age;
StudentTest.java
public class StudentTest {
public static void main(String[] args) {
//객체생성테스트
}
}
[ 도전문제 1 ]
도형 클래스: 다각형(삼각형, 정사각형, 직사각형)의 넓이를 계산하는 클래스를 정의하고 테스트해보세요
=> 필드: String shape, int width, int height, double area
=> 생성자 오버로딩, 메소드 오버로딩(삼각형, 정사각형, 직사각형 넓이)
Polygon.java
public class Polygon {
String shape;
int width,height;
double area;
Polygon(String shape, int width){
this.shape=shape;
this.width=width;
}
Polygon(String shape, int width, int height){
this(shape, width);
this.height=height;
}
//정사각형
void calcArea(int width) {
area=width*width;
}
//삼각형, 직사각형
void calcArea(int width,int height,int s) {
if(s==1)
area=(width*height)/2.0;
else if(s==2)
area=width*height;
}
//출력
void printArea() {
System.out.println(shape);
System.out.println("area"+area);
}
}
PolygonTest.java
package sec02;
import java.util.*;
public class PolygonTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
Polygon p=null;
System.out.print("menu select 1)삼각형 2)직사각형 3) 정사각형:");
int select=s.nextInt();
switch(select) {
case 1:
p=new Polygon("Triangle",10,20);
p.calcArea(p.width,p.height,select);
break;
case 2:
p=new Polygon("Rectangle",10,20);
p.calcArea(p.width,p.height,select);
break;
case 3:
p=new Polygon("square",10);
p.calcArea(p.width);
break;
default:break;
}
p.printArea();
}
}
[ 도전문제 2 ]
계산기 클래스: 두 정수를 사용자로부터 입력 받아 계산 결과를 출력하는 프로그램을 작성하시오
=>필드: int num1, int num2
=>메소드: +,-,*,/
Calculator.java
package sec02;
public class Calculator {
int num1,num2;
//생성자
Calculator(int num1,int num2){
this.num1=num1;
this.num2=num2;
}
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
int add(int num1, int num2) {
return num1+num2;
}
int sub(int num1, int num2) {
return num1-num2;
}
int mul(int num1, int num2) {
return num1*num2;
}
//*** 중요 형변환:묵시적형변환/명시적형변환***
double div(int num1, int num2) {
return (double)num1/num2;
}
void showinfo(String op) {
double result=0.0;
if(op.equals("+"))
result=add(num1, num2);
else if(op.equals("-"))
result=sub(num1, num2);
else if(op.equals("*"))
result=mul(num1, num2);
else if(op.equals("/")) {
if(num2==0) {
System.out.println("Indivisible by zero");
return;
}
result=div(num1, num2);
}
System.out.println("result: "+result);
}
}
CalculatorTest.java
package sec02;
import java.util.*;
public class CalculatorTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
int num1,num2;
String op;
System.out.print("num1:");
num1=s.nextInt();
System.out.print("operator:");
op=s.next();
System.out.print("num2:");
num2=s.nextInt();
Calculator c=new Calculator(num1,num2);
//
c.showinfo(op);
s.close();
}
}
3주차
< 클래스와 객체 (2) >
- 자바 메모리 영역
=> 메소드 영역 = 클래스 영역 = 정적 영역
=> 힙 영역 : 객체와 배열이 생성되는 영역
=> 스택 영역 : 지역변수(초기화 안하면 오류 발생!!)
1. 인스턴스 멤버와 정적 멤버
- 인스턴스 멤버: 겍체마다 가지고 있는 멤버 (인스턴스 필드, 인스턴스 메소드)
package sec01;
class Student{
String name; //인스턴스 변수
void setName(String name) { //인스턴스 메소드
this.name=name;
}
public class InstanceMemTest {
public static void main(String[] args) {
Student s1=new Student();
s1.setName("구글신");
System.out.println(s1.name);
}
}
- 정적멤버: 객체와 상관없는 멤버로 메소드 영역에 위치
static 키워드 사용
=> 정적 필드 및 상수: 객체 없이 클래스만으로도 사용 가능한 필드(클래스.변수명)
=> 정적 메소드: 객체 없이 클래스만으로도 호출 가능한 메소드(클래스.메소드명)
=> 정적 멤버: 클래스 이름과 함께 도트연산자(.)로 접근 (클래스.변수명, 클래스.메소드명)
package sec01;
import java.util.*;
class Circle{
static double PI=3.14; //정적변수
static double area(double r) { //정적메소드
double area=PI*r*r;
return area;
}
}
public class StaticMemTest {
public static void main(String[] args) { //정적메소드
System.out.print("반지름 입력:");
Scanner sc=new Scanner(System.in);
double r=sc.nextDouble();
System.out.println(Circle.area(r)); //정적메소드 호출
sc.close();
}
}
인스턴스 멤버와 정적 멤버 차이점:
- 인스턴스 멤버 = 겍체마다 가지고 있는 멤버(필드, 메소드)
- 정적 멤버 = 객체들이 공유하는 멤버
- 정적 멤버 선언: static 키워드 사용 / 정적 멤버 사용할 때는 객체 생성 필요 X
- 정적 메소드에서는 정적 필드만, 정적 메소드만 사용 또는 호출 가능
- 정적 메소드 선언 시 내부에 인스턴스 필드나 메소드 사용 X
2. 메소드 인수 전달 방법
- 기초형 값이 전달되는 경우: call by value
- int, double의 기본자료형의 경우 인수의 값이 매개변수로 복사된다. = 값에 의한 호출 방식
- 호출된 메소드의 매개변수의 값이 변경되어도 메소드 외부에 있는 인수에게는 영향을 주지 않는다
package sec02;
public class CallTest1 {
public static void main(String[] args) {
int x=10;
System.out.println("x="+x);
add(x);
System.out.println("x="+x);
}
static void add(int x) {
x++;
}
}
실행결과??
- 주소가 전달되는 경우: call by reference
- 객체가 인자로 전달되는 경우 : 객체를 가리키는 주소가 전달됨
package sec02;
class Circle{
int r;
Circle(int r) {
this.r=r;
}
}
public class CallTest2 {
public static void main(String[] args) {
Circle c=new Circle(10);
System.out.println("radius=" + c.r);
size(c); //객체전달
System.out.println("radius=" + c.r);
}
static void size(Circle c) {
c.r++;
}
}
- 배열이 인자로 전달되는 경우
package sec02;
public class CallTest2 {
public static void main(String[] args) {
int arr[]={10,20};
System.out.println(arr[0]+","+arr[1]);
swap(arr);
System.out.println(arr[0]+","+arr[1]);
}
static void swap(int arr[]) {
int tmp=arr[0];
arr[0]=arr[1];
arr[1]=tmp;
}
}
3. 객체 배열 : 객체에 대한 레퍼런스를 원소로 갖는 배열
- 객체에 대한 참조값이 저장됨
객체 정적 배열 생성
package sec02;
public class Song {
String singer;
String title;
Song(String singer, String title) {
this.singer=singer;
this.title=title;
}
}
package sec02;
import java.util.*;
public class SongTest {
public static void main(String[] args) {
Scanner s=new Scanner(System.in);
Song[] list=new Song[3];
for(int i=0; i<list.length; i++) {
System.out.print("가수명:");
String singer=s.nextLine();
System.out.print("타이틀곡:");
String title=s.nextLine();
list[i]=new Song(singer,title);
}
//출력
for(int i=0; i<list.length; i++)
System.out.println("("+list[i].singer+","+list[i].title+")");
}
}
객체 동적 배열 생성
package sec02;
public class Song {
String singer;
String title;
Song(String singer, String title) {
this.singer=singer;
this.title=title;
}
}
package sec02;
import java.util.ArrayList;
public class SongTest2 {
public static void main(String[] args) {
ArrayList<Song> list=new ArrayList<Song>();
list.add(new Song("방탄", "Zero O'clock"));
list.add(new Song("방탄", "Dynamite"));
list.add(new Song("제이슨므라즈", "lucky"));
for(Song s:list)
System.out.println("("+s.singer+","+s.title+")");
}
}
[ 실습문제 1]
판매 클래스(Sales) 선언 : 24시간 아이스크림 가게에서 하루에 판매되는 아이스크림 개수를 알고자 한다. 아이스크림 개수를 알기 위해 아이스크림이 얼마나 판매되었는지 알아야 한다. 정적변수를 선언하고 생성자에서 판매개수를 증가시켜보자. Sales 클래스에 정적변수를 반환하는 정적메소드인 getSales()를 추가하고 SalesTest 클래스에서 테스트해보세요. (난이도 하)
//클래스 선언 : Sales.java
public class Sales {
static int cnt;
Sales(){
cnt++;
}
static int getSale() {
return cnt;
}
}
// 실행클래스 : SalesTest.java
public class SalesTest {
public static void main(String[] args) {
for(int i=0;i<3;i++)
new Sales();
System.out.println("판매된 개수:"+Sales.getSale());
}
}
[ 실습문제 2]
배열(정적배열)을 받는 메소드 작성
- 저번 학기 점수를 배열에 초기화한 후 최대값, 최소값을 계산하여 반환하는 maxArray(), minArray() 를 작성하고 테스트해보세요. (난이도 중)
//클래스 선언 : Array.java
public class Array {
int minArray(int[] score) {
int min=score[0];
for(int i=1;i<score.length;i++) {
if(score[i]<min)
min=score[i];
}
return min;
}
int maxArray(int[] score) {
int max=score[0];
for(int i=1;i<score.length;i++) {
if(score[i]>max)
max=score[i];
}
return max;
}
}
// 실행클래스 : ArrayTest.java
import java.util.*;
public class ArrayTest {
public static void main(String[] args) {
int[] score=new int[5];
Scanner s=new Scanner(System.in);
Array arr=new Array();
System.out.println("저번학기 이수 과목의 점수를 입력하세요(5과목):");
System.out.println(">>");
for(int i=0;i<score.length;i++)
score[i]=s.nextInt();
for(int i=0;i<score.length;i++)
System.out.print(score[i]+" ");
System.out.println();
System.out.println("max:"+arr.maxArray(score));
System.out.println("min:"+arr.minArray(score));
}
}
[ 미션문제 ]
회원정보관리 프로그램
1. 학교 홈페이지 사용자의 아이디와 패스워드를 저장하는 객체 배열을 생성해보자. 실행결과를 참고해서 클래스를 설계하고 객체를 생성하여 테스트해보세요
2. 등록된 사용자수는 정적 변수로 구현하시오. (난이도 상)
// 클래스 선언 : User.java
class User {
String id, pw;
static int cnt;
User(String id, String pw) {
this.id = id;
this.pw = pw;
}
static void show() {
System.out.println("====================================");
System.out.println("1. 회원가입");
System.out.println("2. 회원조회");
System.out.println("3. 종료");
System.out.println("====================================");
System.out.print("번호를 입력하시오: ");
}
}
// 실행클래스: UserTest.java
import java.util.Scanner;
public class UserTest {
public static void main(String args[]) {
User[] list = new User[100];
Scanner scanner = new Scanner(System.in);
while (true) {
User.show(); //정적메소드 호출
int menu = scanner.nextInt();
switch (menu) {
case 1:
System.out.print("id: ");
String id = scanner.next();
System.out.print("pw: ");
String pw = scanner.next();
list[User.cnt] = new User(id, pw);
User.cnt++;
break;
case 2:
for (int i=0;i<User.cnt; i++)
System.out.println("{ " + list[i].id + ", " + list[i].pw + " }");
System.out.println("총 회원수는 "+User.cnt+"명 입니다.");
break;
case 3:
System.out.println("Exit");
System.exit(0);
}
}
}
}
4주차
< 상속 >
V 상속의 개념과 필요성
V 상속과 생성자 ( 생성자 호출과 실행순서 / 묵시적 호출과 명시적 호출 )
V 메소드 오버라이딩
- 이미 개발된 클래스를 재사용하여 새로운 클래스를 만들기에 중복되는 코드를 줄임
- 클래스 재사용과 확장을 통한 소프트웨어의 생산성 향상
클래스 상속
- 자식 클래스 선언 시 부모 클래스 선택
- extends 뒤에 부모 클래스 기술
- 여러 개의 부모 클래스 상속할 수 없음.(다중상속이 안 됨)
- 부모 클래스에서 private 접근 제한자를 갖는 필드와 메소드는 상속 대상에서 제외
- 부모와 자식 클래스가 다른 패키지에 존재할 경우 default 접근 제한된 필드와 메소드 역시 제외
1. 접근제한자
클래스와 인터페이스 및 이들이 가진 멤버의 접근 제한
- public 접근 제한자 : 외부 클래스가 자유롭게 사용할 수 있도록 함
- protected 접근 제한자 : 같은 패키지 또는 자식 클래스에서 사용할 수 있도록 함
- default 접근 제한자 : 같은 패키지에 소속된 클래스에서만 사용할 수 있도록 함
- private 접근 제한자 : 오직 클래스 내부에서만 접근할 수 있음
- Getter 메소드 / 선언 예 : getXXX(), isXXX()
- 외부로 필드값을 전달하는 것이 목적
- 필드값을 가공해서 외부로 전달할 수도 있음
- Setter 메소드 / 선언 예 : setXXX()
- 외부의 값을 받아 필드의 값을 변경하는 것이 목적
- 매개값 검증하여 유효한 값만 필드로 저장할 수 있음
2. 클래스 상속
예제) (x,y)의 한 점을 표현하는 Point클래스와 이를 상속받아 점에 색을 추가한 ColorPoint클래스를 만들고 활용해보자
//step1: 부모클래스(슈퍼클래스 정의)
class Point {
private int x,y;
void setPoint(int x, int y) {
this.x=x;
this.y=y;
}
void showPoint() {
System.out.println("("+x+","+y+")");
}
}
//step2: 자식클래스(서브클래스/파생클래스 정의)
class ColorPoint extends Point{
private String colorl
void setColor(String color) {
this.color=color;
}
void showColorPoint() {
System.out.println(color);
showPoint(); //부모클래스 메소드 호출
}
}
//step3: 실행클래스
package sec01;
public class ColorPointTest {
public static void main(String[] args) {
Poing p=new Point();
p.setPoint(10,20);
p.showPoint();
ColorPoint cp=new ColorPoint();
cp.setPoint(20,30);
cp.setColor("red");
cp.showColorPoint();
}
)
3. 상속과 생성자
q1 : 자식클래스의 객체가 생성될 때, 자식클래스의 생성자와 부모클래스의 생성자는 모두 실행되는가? 아니면 자식클래스의 생성자만 실행되는가?
=> 자식 객체 생성할 때 부모 객체가 먼저 생성되고 그 다음 자식 객체가 생성됨
q2 : 자식클래스의 생성자와 부모 클래스의 생성자 중 누가 먼저 실행되는가?
=> 자식 생성자의 맨 첫 줄에서 부모 생성자가 호출됨.
부모클래스의 기본생성자 묵시적 호출(컴파일러)
명시적으로 부모 클래스의 생성자 호출(super())
예제1)
예제2)
//step1: 부모클래스 정의
package sec01;
public class People {
String name;
String ssn;
People(String name, String ssn) {
this.name=name;
this.ssn=ssn;
}
}
//step2: 자식 클래스 정의
package sec01;
public class Student extends People {
int stuNo;
Student(String name, String ssn, int stuNo) {
super(name,ssn);
this.stuNo=stuNo;
}
}
//step3: 실행클래스
package sec01;
public class StudentTest {
public static void main(String[] args) {
Student s1=new Student("자바신", "1234567-1234567", 100);
System.out.println("name:"+s1.name);
System.out.println("ssm:"+s1.ssn);
System.out.println("stuNo:"+s1.stuNo);
}
}
4. 메소드 오버라이딩
: 부모 클래스의 메소드가 자식 클래스에서 사용하기에 부적합할 경우 자식 클래스에서 수정하여 사용
- 부모 메소드와 동일한 시그니처 가져야 함
- 접근 제한 더 강하게 재정의할 수 없음
메소드가 재정의될 경우 부모 객체 메소드가 숨겨지며, 자식 객체에서 메소드 호출하면 재정의된 자식 메소드가 호출됨
예제1)
원의 넓이를 계산하는 메소드를 Calculator 클래스에 정의하고, Computer 자식 클래스에서 메소드 오버라이딩해보자.
//step1: 부모클래스 정의
package sec01;
public class Calculator {
double areaCircle(double r) {
double area=3.1415*r*r;
return area;
}
}
//step2: 자식 클래스 정의
package sec01;
public class Computer extends Calculator {
@Override
double areaCircle(double r) {
double area=Math.PI*r*r;
return area;
}
}
//step3: 실행 클래스
package sec01;
public class ComputerTest {
public static void main(String[] args) {
int r=10;
Calculator cal=new Calculator();
System.out.println("원의 면적"+cal.areaCircle(r));
Computer com=new Computer();
System.out.println("원의 면적"+com.areaCircle(r));
}
}
** 부모 메소드 호출 **
자식 클래스 내부에서 재정의된 부모 클래스 메소드 호출해야 하는 경우
명시적으로 super 키워드 붙여 부모 메소드 호출
[ 도전문제 ]
회사 직원들의 급여를 계산하는 프로그램
문제 : 이 회사의 직원 중에는 매니저가 있고 매니저 중에는 임원이 있다.
➲ 모든 직원은 이름을 가지고 급여를 받는다.
➲ 매니저는 급여 외 보너스를 받을 수 있다.
➲ 임원은 급여와 보너스 외 스톡옵션을 받는다.
➲ 직급에 따라 매년 급여 인상률이 다르다.
➲ 이 문제를 해결하기 위해 필요한 클래스들을 정의하고 전체 프로그램을 제어하는 실행클래스를 정의하여 테스트하시오.
package sec02;
public class Employee {
protected String name; // 이름
protected int salary;// 급여
// 생성자 메소드
public Employee (String name, int salary)
{
this.name = name;
this.salary = salary;
}
// 이름을 반환한다
public String getName()
{
return name;
}
// 급여를 반환한다
public int getSalary()
{
return salary;
}
// 급여를 올린다
public int raiseSalary()
{
int increased_salary;
increased_salary = (int)(salary * 1.3);
return increased_salary;
}
// 객체의 현 상태를 반환한다.
public String showInfo() {
String result="\n이름:"+name;
result+="\n급여:"+salary;
result+="\n인상된 급여:"+raiseSalary();
return result;
}
}
package sec02;
//임원을 모델링한다.
public class Executive extends Manager{
private int stockOption; // 스톡 옵션
// 생성자 메소드
public Executive (String name, int salary, int bonus, int stockOption)
{
super(name, salary, bonus);
this.stockOption = stockOption;
}
// 스톡 옵션을 반환한다
public int getStockOption()
{
return stockOption;
}
// 급여를 올린다
public int raiseSalary()
{
int increased_salary;
increased_salary = (int)(salary * 1.1);
return increased_salary;
}
// 객체의 현 상태를 반환한다.
public String showInfo() {
String result=super.showInfo();
result+="\n스톡옵션:"+stockOption;
return result;
}
}
package sec02;
public class InheritanceTest {
public static void main(String[] args) {
// 객체들을 생성한다.
Employee emp = new Employee("강길동", 100000);
Manager mng = new Manager("고길동", 200000, 50000);
Executive exc = new Executive("홍길동", 400000, 100000, 100000);
// 각 객체의 급여를 올린다
emp.raiseSalary();
mng.raiseSalary();
exc.raiseSalary();
// 결과를 출력한다
System.out.println("===Employee(직원)===");
System.out.println(emp.showInfo());
System.out.println();
System.out.println("===Manager(매니저)===");
System.out.println(mng.showInfo());
System.out.println();
System.out.println("===Executive(임원)===");
System.out.println(exc.showInfo());
System.out.println();
}
}
package sec02;
public class Manager extends Employee {
protected int bonus; // 보너스
// 생성자 메소드
public Manager (String name, int salary, int bonus)
{
super(name, salary);
this.bonus = bonus;
}
// 보너스를 반환한다
public int getBonus()
{
return bonus;
}
// 급여를 올린다
public int raiseSalary()
{
int increased_salary;
increased_salary = (int)(salary * 1.2);
return increased_salary;
}
// 객체의 현 상태를 반환한다.
public String showInfo() {
String result=super.showInfo();
result+="\n보너스:"+bonus;
return result;
}
}
5주차
< 추상클래스와 인터페이스 >
V 추상클래스 (개념, 용도 / 추상메소드 / 정의방법 )
V 인터페이스 (개념, 용도 / 정의, 구현 방법 )
V 추상클래스와 인터페이스 차이점
1. 추상클래스 개념, 선언방법, 목적
- 추상화: 구체적인 개념으로부터 공통된 부분들만 추려내어 일반화할 수 있도록 하는 것
- 추상클래스는 실체 클래스의 공통적인 부분을 추출해 어느 정도 규격을 잡아놓은 추상적인 클래스
- 실체클래스의 공통적인 부분(변수,메소드)를 추출해서 선언한 클래스
- 추상 클래스(부모)와 실체 클래스(자식)는 상속 관계를 가짐
- 추상 클래스는 추상 메소드, 일반 메소드, 필드(멤버변수), 생성자로 구성된다.
2. 추상메소드 개념
- 메소드 선언만 통일하고 실행 내용은 실체 클래스마다 달라야 하는 경우
- abstract 키워드로 선언되고 중괄호가 없는 메소드
- 하위 클래스는 반드시 재정의해서 실행 내용을 결정해야 함
추상 클래스 용도:
- 공통된 필드와 메소드를 통일할 목적
➲ 필드와 메소드를 통일시켜 유지보수성을 높이고 통일성을 유지
- 실체클래스 구현시 시간절약
- 규격에 맞는 실체클래스 구현
➲ 추상클래스를 상속받은 실체클래스들은 반드시!! 추상메소드를 재정의(오버라이딩)해서 실행 내용을 작성해야 함
추상 클래스 선언:
- abstract 키워드
- 상속 통해 자식 클래스만 만들 수 있게 만듦 (부모로서의 역할만 수행하게)
- 추상 클래스도 일반 클래스와 마찬가지로 필드, 생성자, 메소드 선언 할 수 있음
- 직접 객체 생성 X but 객체 생성될 때 객체화 됨
- 추상메소드를 가질 수 있다
추상 클래스 목적:
- 상속 위한 슈퍼클래스로 활용
- 서브 클래스에서 추상 메소드 구현
- 다형성
예제)
Shape 클래스는 도형의 이름을 필드로 가지며, 면적과 둘레에 대한 추상메소드를 정의
//step1: 추상 클래스(슈퍼클래스) 정의
package sec01;
//추상클래스 선언
//Shape.java : 일반적인 모양 선언
abstract class Shape {
protected String name;
String getName() {
return name;
}
//추상메소드 선언: 면적
abstract double getArea();
//추상메소드 선언: 둘레
abstract double getPerimeter();
//추상메소드 선언: 출력
abstract void showInfo();
}
//step2: Rectangle 자식클래스 정의
//step2: Circle 자식클래스 정의
//step3: 실행 클래스 정의
package sec01;
public class ShapeTest{
public static void main(String[] args) {
Rectangle myRect=new Rectangle("AA",10,20);
myRect.showInfo();
Circle myCircle=new Circle("BB",5);
myCircle.showInfo();
}
}
3개의 공통 기능은 일반 메소드로 작성하고 1개의 다른 기능은 추상메소드로 구현한다. 그러면 이 추상클래스를 extends 하여 추상메소드만 다르게 구현함으로써 효율적인 코드를 작성할 수 있게 된다
3. 인터페이스 개념, 구현방법, 목적
인터페이스 정의 및 구현:
- 인터페이스는 interface 키워드를 통해 선언할 수 있으며 implements 키워드를 통해 일반 클래스에서 인터페이스를 구현할 수 있다.
- 인터페이스는 상수와 추상 메소드(디폴트메소드,정적메소드)로 이뤄진다.
- 인터페이스 멤버들은 모두 묵시적으로 public abstract이다.
- 구현클래스에서 인터페이스를 사용하기 위해서는 implements 예약어를 사용
- 구현클래스에서 인터페이스를 사용할 경우 반드시 정의된 메소드를 오버라이딩하여 구현해야 한다.
- 인터페이스는 다중 상속이 가능하다.
예제)
리모컨 인터페이스
- 상수필드 : MAX_VOLUME, MIN_VOLUME
- 추상메소드 : turnOn(), turnOff(), setVolume()
//step1 : 인터페이스 정의
package sec02;
public interface RemoteControl {
int MAX_VOLUME=10;
int MIN_VOLUME=0;
//추상메소드 선언
void turnOn();
void turnOff();
void setVolume(int volume);
}
//step2 : 인터페이스 구현 클래스
package sec02;
public class Television impementes RemoteControl {
private int volume;
@Override
public void turnOn() {
}
@Override
public void turnOff() {
}
@Override
public void setVolume(int volume) {
}
}
//step3 : 실행 클래스
package sec02;
public class RemoteControlTest {
public static void main(String[] args) {
Television tv=new Television();
tv.turnOn();
tv.setVolume(5);
tv.turnOff();
}
}
4. 추상클래스와 인터페이스 차이점
추상클래스는 추상클래스를 상속받아서 자식이 그 기능을 이용하고 확장하는 데 있다.
vs
인터페이스는 메소드의 구현을 강제적으로 시키기 위해서 구현을 강제함으로써 구현 객체의 같은 동작을 보장시킬 수 있다
6주차
< 패키지와 예외처리 >
V 패키지 ( 패키지 개념과 필요성 / 패키지 선언과 활용 )
V 예외처리 (예외처리 개념 / 예외종류 / 예외처리 방법)
1. 패키지 개념과 필요성
- 클래스들을 분류하고 사용의 편리성을 제공하기 위해서 관련 클래스와 인터페이스들을 하나로 묶을 수가 있는데 이를 패키지(package) 이라고 한다.
- 즉, 패키지는 비슷한 종류의 클래스나 인터페이스들을 하나의 집단 으로 묶어 놓은 것을 말한다.
✓ 클래스 들을 하나로 묶어놓은 것이다.
✓ 클래스 간의 이름 중복으로 발생하는 충돌을 막아준다.
✓ 클래스를 기능 별로 분류할 수 있어 필요한 클래스의 식별이 용이하다
==> 다른 패키지에 작성된 클래스 사용 <===
- import 이용하지 않는 경우
소스에 클래스 이름의 완전 경로명 사용
- 필요한 클래스만 import
- 소스 시작 부분에 클래스의 경로명 import
- import 패키지.클래스
- 소스에는 클래스명만 명시하면 됨
- 패키지 전체를 import
- 소스 시작 부분에 패키지의 경로명.* import
- import 패키지.*
- 소스에는 클래스명만 명시하면 됨
- import java.util.* (java.util 패키지 내의 모든 클래스만을 지정, 하위 패키지의 클래스는 포함 X)
2. 패키지 만들기
V 클래스 파일(.class)이 저장되는 위치는?
클래스나 인터페이스가 컴파일되면 클래스 파일(.class) 생성
클래스 파일은 패키지로 선언된 디렉터리에 저장
V 패키지 선언
소스 파일의 맨 앞에 컴파일 후 저장될 패키지 지정 (package 패키지명;)
Calculator 클래스는 lib 패키지에
GoodCalc 클래스는 app 패키지에 나누어 저장하는 프로그램 만들기
// lib 패키지에 클래스 Calculator 만들기 (
package lib;
public abstract class Calculator { // app 패키지 접근 위해 public 중요
public abstract int add(int a, int b);
public abstract int substract(int a, int b);
public absract double average(int[] a);
}
// app 패키지에 클래스 GoodCalc 만들기
package app;
import lib.Calculator; //Calaculator 클래스 사용 위해 패키지를 포함하는 정확한 경로명 알려줘야함
public class GookCalc extends Calculator{
@Override
public int add(int a, int b) { //추상메소드 구현
return a+b;
}
@Override
public int substract(int a, int b) { //추상메소드 구현
return a-b;
}
@Override
public double average(int[] a) { //추상메소드 구현
double sum=0;
for (int i = 0; i < a.length; i++)
sum += a[i];
return sum/a.length;
}
}
//app 패키지에 실행클래스 PackageTest 만들기
package app;
public class PackageTest {
public static void main(String[] args) {
int num[]={1,2,3};
GoodCalc c = new GoodCalc();
System.out.println(c.add(1,2));
System.out.println(c.substract(1,2));
System.out.println(c.average(num));
}
}
[ 수업 중 실습 ]
package lib
Calculator.java
package lib;
public abstract class Calculator {
//추상메소드 : 덧셈(add), 뺄셈(sub), 곱셈, 나눗셈, 평균(avg)
public abstract int add(int a, int b);
public abstract int sub(int a, int b);
public abstract double avg(int[] arr);
}
package app
GoodCalc.java
package app;
import lib.Calculator;
public class GoodCalc extends Calculator{
public static void main(String[] args) {
// TODO Auto-generated method stub
//테스트
int[] arr= {10,20,30};
GoodCalc c=new GoodCalc();
System.out.println(c.add(10, 20));
System.out.println(c.sub(10, 20));
System.out.println(c.avg(arr));
}
@Override
public int add(int a, int b) {
// TODO Auto-generated method stub
return a+b;
}
@Override
public int sub(int a, int b) {
// TODO Auto-generated method stub
return a-b;
}
@Override
public double avg(int[] arr) {
// TODO Auto-generated method stub
int sum=0;
double avg;
for(int i:arr)
sum+=i;
avg=(double)sum/arr.length;
return avg;
}
}
3. 주요 패키지 활용
- java.lang
◼ 스트링, 수학 함수, 예외처리 등 자바 프로그래밍에 필요 한 기본적인 클래스와 인터페이스
◼ 자동으로 import 됨 --> import 문 필요 없음
- java.io
◼ 키보드, 모니터, 프린터, 디스크 등에 입출력을 할 수 있는 클래스와 인터페이스 제공
- java.awt
◼ GUI 프로그램을 작성하기 위한 AWT 패키지
- javax.swing
◼ GUI 프로그래밍을 작성하기 위한 스윙 패키지
- java.util
◼ 날짜, 시간, 벡터, 해시맵 등과 같은 다양한 유틸리티 클래스와 인터페이스 제공
◼ 프로그램을 개발하는 데 사용할 수 있는 유용한 유틸리티 클래스가 다수 포함
- java.util.Arrays 클래스
Arrays 클래스에는 배열을 다루기 위한 다양한 메소드가 포함되어 있음
Arrays 클래스의 모든 메소드는 클래스 메소드(static method)이므로, 객체를 생성하지 않고도 바로 사용할 수 있음.
- java.util.Random 클래스
Random 클래스는 난수 발생시킬 수 있는 객체
- java.util.Calendar 클래스
추상클래스로 날짜와 시간에 대한 정보를 가지고 있고 특정 시각을 연도, 월, 일 등으로 변환하는 메소드도 가짐
[ 수업 중 실습 ]
//학번 이름
package app;
import java.util.Arrays;
import java.util.Scanner;
public class ArrayTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
int num;
int[] arr= {50,15,60,40,20};
//정렬, 검색 알고리즘
System.out.println("정렬 전:");
show(arr);
//System.out.println(Arrays.binarySearch(arr, 40));
Arrays.sort(arr);// 내림차순
System.out.println("\n정렬 후:");
show(arr);
// 검색 : 선형검색, 이분검색(binarysearch)
System.out.println();
// 사용자로부터 필요한 데이터를 입력받는다.
System.out.print("점수 입력: ");
num = s.nextInt();
int idx=Arrays.binarySearch(arr, num);
if(idx<0)
System.out.println("검색실패");
else
System.out.println(idx+1+"번째 위치함");
}
//배열요소출력 메소드정의
static void show(int[] arr) {
for(int i:arr)
System.out.print(i+" ");
}
}
4. 예외 처리 개념과 활용
예외(Exception) : 프로그램 실행 중에 발생되는 비정상적인 상황
** 프로그래밍에서 에러(Error)는 2가지 **
• 컴파일(Complie) 시 발생하는 에러
• 런타임(Runtime) 시에 발생하는 에
(객체를 선언만 하고 생성하기 전에 참조를 한 경우 / 0으로 정수를 나눴을 경우 / 배열의 크기에 벗어난 인덱스를 접근한 경우 / 파일을 접근을 하려고 하는데 실제 파일이 없는 경우 등)
자바는 런타임 시에 발생하는 에러를 예외(Exception)이라고 부르고, 예외 상황을 처리할수 있게 다양한 클래스를 제공
예외 처리 : 발생한 예외에 대해 개발자가 작성한 프로그램 코드에서 대응하는 것
==> try-catch-finally문 사용 (finally 생략 가능)
자바 예외 클래스 => 실행 중 오류 탐지할 수 있도록 많은 예외를 클래스 형태로 제공
1) 예외처리 : 0으로 나누는 예외처리
package app;
import java.util.*;
public class DividByZeroTest {
public static void main(String[] args) {
int x,y;
Scanner s=new Scanner(System.in);
System.out.print("피젯수:");
x=s.nextInt();
System.out.print("젯수:");
y=s.nextInt();
try {
int result=x/y;
System.out.println("결과:"+result);
} catch (ArithmeticException e) {
System.out.println("0으로 나눌 수 없음");
}
finally {
s.close();
}
}
}
2) 예외처리 : 배열의 범위를 벗어날 경우
package app;
public class ArrayExceptionTest {
public static void main(String[] args) {
int[] arr = new int[5];
try {
for(int i=0; i<=arr.length; i++)
arr[i]=100;
} catch (ArrayIndexOutofBoundsException e) {
System.out.println("배열의 범위를 초과함");
}
}
}
[ 미션문제 ]
한 교과목의 성적을 처리하는 프로그램
➲ 교과목을 수강하는 학생들은 학부생과 대학원생들로 나누어진다.
➲ 각 학생은 학생유형, 이름, 점수, 학점을 가진다
➲ 학점은 학생 유형에 따라 다음 기준에 의해 통과 혹은 과락 중의 하나가 주어진다.
➲ 학생의 유형, 이름과 점수를 입력 받아 학점을 계산한 후 출력해야 한다.
➲ 학생, 학부생과 대학원생을 나타내는 클래스를 설계하고 작성하시오. 또한 실행클래스를 정의하여 테스트하시오.
** Student 클래스 설계 **
학부생들과 대학원생들의 공통적인 데이터는 학생유형, 이름, 점수, 학점이다.
학생과 관련된 연산은 다음과 같다.
1) Student 객체를 생성한다.
2) 학생유형을 주어진 값으로 변경한다.
3) 이름을 주어진 값으로 변경한다.
4) 점수를 주어진 값으로 변경한다.
5) 학점을 계산한다.
6) 학생유형을 반환한다.
7) 이름을 반환한다.
8) 점수를 반환한다.
9) 학점을 반환한다.
학점을 계산하는 메소드는 필요하나 학부생이냐 대학원생이냐에 따라 다르게 작성되어야 하므로 추상메소드로 구현한다. 즉, Student클래스는 추상 클래스가 된다
//GraduateStudent.java
package sec01;
//대학원생을 모델한다
class GraduateStudent extends Student
{
// 생성자
public GraduateStudent(String name)
{
super(name);
}
// 학점을 계산한다
public void computeGrade( )
{
if (score >= 80)
grade = "통과";
else
grade = "과락";
}
}
//Student.java
package sec01;
//학생을 모델한다
abstract class Student
{
protected int type; // 학부생(1), 대학원생(2)
protected String name; // 이름
protected int score; // 점수
protected String grade; // 학점
// 생성자 정의
public Student (String name)
{
this.name=name ;
}
// 학생유형을 반환한다
public int getType( )
{
return type ;
}
// 이름을 반환한다
public String getName( )
{
return name ;
}
// 점수를 반환한다
public int getScore( )
{
return score;
}
// 학점을 반환한다
public String getGrade( )
{
return grade ;
}
// 레벨을 주어진 값으로 변경한다
public void setType (int type)
{
this.type = type ;
}
// 이름을 주어진 값으로 변경한다
public void setName (String name)
{
this.name = name ;
}
// 점수를 주어진 값으로 변경한다
public void setScore (int score)
{
this.score = score ;
}
// 추상 메소드: 학점을 계산한다
// 반환값이 있는 메소드변경
abstract public void computeGrade();
// 객체 현 상태 반환
public String showInfo() {
String result="소속\t이름\t점수\t학점\n";
if(type==1)
result += "학부생";
else
result += "대학원생";
result += "\t"+getName();
result += "\t"+getScore();
result += "\t"+getGrade();
return result;
}
}
//UndergraduateStudent.java
package sec01;
//학부생을 모델한다
class UndergraduateStudent extends Student
{
// 생성자
public UndergraduateStudent(String name)
{
super(name);
}
// 학점을 계산한다
public void computeGrade( )
{
if (score >= 70)
grade = "통과";
else
grade = "과락";
}
}
//StudentTest.java
package sec01;
import java.util.Scanner;
public class StudentTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner s=new Scanner(System.in);
String name;
int score,type;
// 사용자로부터 필요한 데이터를 입력받는다.
System.out.print("학생유형(학부생=1, 대학원생=2): ");
type=s.nextInt();
System.out.print("이름 입력: ");
name = s.next( );
System.out.print("점수 입력: ");
score = s.nextInt();
UndergraduateStudent us=new UndergraduateStudent(name); //학부생
GraduateStudent gs=new GraduateStudent(name); //대학원생
//각 객체의 레벨, 점수, 학점을 계산 후 결과를 출력한다.
if(type==1) {
us.setType(type);
us.setScore(score);
us.computeGrade();
System.out.println(us.showInfo());
}
else {
gs.setType(type);
gs.setScore(score);
gs.computeGrade();
System.out.println(gs.showInfo());
}
}
}
7주차
< 자바 GUI 프로그램 기초 >
V 자바 GUI 프로그램 기초 ( 컨테이너, 컴포넌트 )
V GUI 프로그램 절차 ( 프레임 만들기 / 컴포넌트 생성 후 부착 / main()메소드 작성 )
V 배치관리자 ( FlowLayout / BorderLayout / GridLayout )
1. GUI 프로그램 개요, 컴포넌트, 컨테이너
GUI(그래픽 사용자 인터페이스)는 컴포넌트들로 구성된다.
** 자바에서 GUI의 종류 **
AWT(Abstract Windowing Toolkit) 패키지
◼ 자바가 처음 나왔을 때부터 배포된 GUI 패키지, 최근에는 거의 사용하지 않음
◼ AWT 컴포넌트는 중량 컴포넌트(heavy weight component)
Swing 패키지
◼ AWT 기술을 기반으로 작성된 자바 라이브러리
◼ 모든 AWT 기능 + 추가된 풍부하고 화려한 고급 컴포넌트
◼ AWT 컴포넌트를 모두 스윙으로 재 작성. AWT 컴포넌트 이름 앞에 J자를 덧붙임
◼ 순수 자바 언어로 구현
◼ 스윙 컴포넌트는 경량 컴포넌트(light weight component)
◼ 현재 자바의 GUI로 사용됨
컨테이너 ( 컴포넌트를 넣을 수 있는 상자 같은~)
: 다른 컴포넌트를 포함할 수 있는 GUI 컴포넌트
◼ Swing 컨테이너 : JPanel JFrame, JApplet, JDialog, JWindow
컴포넌트
: 컨테이너에 포함되어야 화면에 출력될 수 있는 GUI 객체
다른 컴포넌트를 포함할 수 없는 순수 컴포넌트
최상위 컨테이너
: 다른 컨테이너에 포함되지 않고도 화면에 출력되며 독립적으로 존재 가능한 컨테이너
◼ 스스로 화면에 자신을 출력하는 컨테이너 : JFrame, JDialog, JApplet
** 컨테이너와 컴포넌트의 포함관계 **
최상위 컨테이너를 바닥에 깔고, 그 위에 컨테이너를 놓고, 다시 컴포넌트를 쌓아가는 방식
(레고 블록 쌓는 듯~ )
2. GUI 프로그램 절차
첫 윈도우 프로그램
- 클래스 JFrame의 객체를 이용한 윈도우 프로그램
- 패키지가 javax.swing으로 AWT의 Frame을 상속받은 클래스
- 간단한 윈도우 프로그래밍 절차
① JFrame으로 객체 생성: new JFrame()
② 가로와 세로 크기 지정: setSize(가로, 세로)
③ 윈도우 캡션에 표시되는 제목 지정: setTitle(제목)
④ 화면에 표시: setVisible(true)
package sec01;
import javax.swing.*;
public class FirstWindow {
public static void main(String[] args) {
JFrame f=new JFrame();
f.setTitle("첫 윈도우 프로그램");
f.setSize(300, 100);
f.setVisible(true);
}
- 클래스 JFrame를 상속받은 윈도우 프로그램
- JFrame의 상속받아 간단한 윈도우 프로그래밍 절차
package sec01;
import javax.swing.*;
public class HelloFrame extends JFrame{
//생성자
HelloFrame() {
setTitle("첫 번째 윈도우 프로그램");
setSize(300, 100);
setVisible(true);
}
public static void main(String[] args) {
HelloFrame f=new HelloFrame();
}
}
3. 배치관리자
: 컨테이너 안의 각 컴포넌트의 위치와 크기를 결정하는 작업
- 컨테이너의 배치관리자
◼ 컨테이너마다 하나의 배치관리자 존재
◼ 컨테이너에 부착되는 컴포넌트의 위치와 크기 결정
◼ 컨테이너의 크기가 변경되면, 컴포넌트의 위치와 크기 재결정
- 배치관리자 대표 유형 ==> java.awt 패키지에 구현되어 있음
FlowLayout 배치관리자
◼ 컴포넌트가 삽입되는 순서대로 왼쪽에서 오른쪽으로 배치
◼ 배치할 공간이 없으면 아래로 내려와서 반복한다.
BorderLayout 배치관리자
◼ 컨테이너의 공간을 동,서,남,북,중앙의 5개 영역으로 나눔
◼ 5개 영역 중 응용프로그램에서 지정한 영역에 컴포넌트 배치
GridLayout 배치관리자
◼ 컨테이너를 프로그램에서 설정한 동일한 크기의 2차원 격자로 나눔
◼ 컴포넌트는 삽입 순서대로 좌에서 우로, 다시 위에서 아래로 배치
- 컨테이너와 디폴트 배치관리자
: 컨테이너 생성시 자동으로 생성되는 배치관리자
---------------------------------------------------------배치관리자 : BorderLayout ------------------------------------------------------------------
- 컴포넌트들이 5개의 영역인 상, 하, 좌, 우, 중앙 중 하나로 추가.
- 만약, 영역을 지정하지 않으면 컴포넌트는 중앙에 놓여진다.
- 컴포넌트에 배치관리자를 설정하려면 먼저 new연산자를 이용하여 배치관리자 객체를 만들고 이 객체를 컨테이너의 setLayout()메소드를 사용하여 배치 관리자로 지정한다
------------------------------------------------------------배치관리자 : FlowLayout ------------------------------------------------------------------
- 컴포넌트들을 왼쪽에서 오른쪽으로 버튼을 배치한다.
- 패널과 애플릿의 디폴트 배치 관리자이다.
생성자
- FlowLayout()
- FlowLayout(int align, int hGap, int vGap)
◼ align : 컴포넌트를 정렬하는 방법 지정. 왼쪽 정렬(FlowLayout.LEFT), 오른쪽 정렬(FlowLayout.RIGHT), 중앙 정렬(FlowLayout.CENTER(디폴트))
◼ hGap : 좌우 두 컴포넌트 사이의 수평 간격, 픽셀 단위. 디폴트는 5
◼ vGap : 상하 두 컴포넌트 사이의 수직 간격, 픽셀 단위. 디폴트는 5
컨테이너에 새로운 배치관리자 설정
- setLayout(LayoutManager lm) 메소드 호출 ( lm을 새로운 배치관리자로 설정)
- 사례
◼ JPanel 컨테이너에 BorderLayout 배치관리자를 설정하는 예
JPanel p = new JPanel(); p.setLayout(new BorderLayout()); // JPanel에 BorderLayout 설정 |
◼ 오류
c.setLayout(FlowLayout); // 오류 |
--------------------------------------------------------------배치관리자 : GridLayout ----------------------------------------------------------------
- GridLayout은 컴포넌트를 격자 모습으로 배치한다.
- 컨테이너 공간을 동일한 사각형 격자(그리드)로 분할하고 각 셀에 컴포넌트 하나 씩 배치
생성자에 행수와 열수 지정
셀에 왼쪽에서 오른쪽으로, 다시 위에서 아래로 순서대로 배치
생성자
- GridLayout()
- GridLayout(int rows, int cols)
- GridLayout(int rows, int cols, int hGap, int vGap)
◼ rows : 격자의 행수 (디폴트 : 1)
◼ cols : 격자의 열수 (디폴트 : 1)
◼ hGap : 좌우 두 컴포넌트 사이의 수평 간격, 픽셀 단위(디폴트 : 0)
◼ vGap : 상하 두 컴포넌트 사이의 수직 간격, 픽셀 단위(디폴트 : 0)
4. 주요 컴포넌트 설계
패널: 컴포넌트들을 포함하고 있도록 설계된 컨테이너 중 하나
기초 컴포넌트
- 레이블(JLabel) : 편집이 불가능한 텍스트 또는 이미지를 표시할 수 있는 공각
- 텍스트필드(JTextField) : 사용자가 한 줄의 텍스트를 입력할 수 있는 고안
- 버튼(JButton) : 클릭되면 어떤 동작을 실행하는 버튼
[ 과제 ]
GridLayout 피아노 건반 만들기 프로그램을 작성하기
// 과제 작성하기 !!
2020 중간고사 족보
'Study > Java Study' 카테고리의 다른 글
JAVA 프로그래밍 및 실습 [기말 정리 요약본] (0) | 2023.12.05 |
---|---|
12장. 파일 입출력 (0) | 2023.05.28 |
11장. 예외 처리 (0) | 2023.05.28 |
10장. 패키지 (0) | 2023.05.28 |
9장. 추상 클래스와 인터페이스 (0) | 2023.05.22 |