일곱째 날

정혅·2024년 2월 15일

더 조은 아카데미

목록 보기
11/76

구슬치기 문장에서 if문에서 return하는 문장을 굳이 temp에 담아서 하는 이유 스터디때 물어보기


어제 복습 중 추가 개념

class Child{
    String name;
    int beads;
    public Child(String nmae, int beads){
        this.name = name; // 참조변수와 멤버변수의 이름이 같으면 this.꼭 넣어주기 
        beads = beads; //이 경우에는 멤버변수인 beads에 값이 들어가지 않는다.
}
}
  • 멤버변수와 지역변수의 이름이 같다면 this. 꼭 넣어주기 > 아니면 값이 들어가지 않음

  • 멤버 변수가 상수 지정이 안되는것이지, 지역변수에서는 가능하다.

    • 그 변수를 상수로 지정한 메소드가 끝나면 소멸되기 때문에

    • 그러나 멤버변수의 값을 받아와 메소드 파라미터에 상수로 지정하는 형식의 문장은 문법적으로 에러난다.

  • 생성자

    • 클래스 이름과 대소문자 하나까지 같아야하고, 상수인 멤버변수를 초기화가 가능하다. > 멤버변수를 초기화해줄 목적으로 있는..

멤버변수 기본값

  • 지역변수는 초기화 하지 않으면 쓰레기 값이 들어가 있어 반드시 초기화 해줘야한다.

  • 8개의 자료형을 제외한 나머지는 모두 참조형 변수로 null값으로 자동 초기화된다.

    • 멤버 변수 AAA aaa; 는 null값은 AAA참조변수가 참조하는 주소가 없다 하는 목적으로 쓰인다.

Classpath잡는 법

  • 파일에 클래스 3개를 만들고 컴파일하면 3개의 클래스가 생성된다.

  • AAA와 BBB클래스를 다른 파일로 넣고 컴파일하니 AAA클래스를 찾을 수 없다고 오류가 뜬다

    • 기본적으로 컴파일할때 같은 dir안에 있는 파일을 찾아 컴파일하는데 지금은 다른 dir에 있어서 찾지 못한다고 에러가 뜨는것이다.

    • 이것을 이제 classpath를 잡아서 찾을 수 있게 할것이다.

  • set classpath=.;.\sub;

    • 이 문장은 classpath를 잡고, .현재 dir; .\밑에 sub이라는 폴더를 classpath로 잡아서 다시 컴파일하면 오류 x

와일드카드 문자 - cmd

dir = directory의 목록을 불러오는

. = 현재 디렉토리 / .. = 상위 디렉토리

dir * = 모든 목록을 불러온다

dir *.* = 파일의 이름, 확장자 모두 불러오는 > 위 2개와 결과만 놓고보면 같음

dir *.java = 확장자가 java인 모든 파일의 목록을 불러온다

dir *.c* = 확장자가 c로 시작하는 모든 파일의 목록을 불러온다

dir A* = 파일의 이름이 A로 시작하는 모든 파일의 목록을 불러온다.

배치파일

  • javac -d . *.java = 확장자가 java인 모든 파일을 컴파일하는데, 패키지까지 함께 컴파일해라

    • javac *.java = 확장자가 java인 모든 파일을 컴파일해라
  • mkdir sub = sub라는 dir을 만들어라

  • move AAA.class .\sub\AAA.class = move 는 옮기는 명령어이자 이름은 바꾸는데 사용할 수 있다. 현재 디렉토리에 있는 AAA.class를 현재 디렉토리 밑에 sub라는 파일속 AAA.class라는 이름으로 옮기라는 문장

  • set classpath=.;.\sub; = 클래스패스를 설정하는

    • java ABMain
  • pause = 멈추게하는 명령(사용하지 않으면 명령창이 꺼진다.)

  • 실행하고 싶은 동작을 .bat파일로 저장해서 실행하면 자동으로 얘가 동작해준다.

    • 실행은 그냥 .bat으로 저장한 파일 눌러주면 cmd가 켜지면서 자동실행


Package

  • 패키지는 사용할때 package 하고 속해있는 파일들을 나열해 선언해야한다.

public class 의 문법

어디서나 접근 가능하다

다른 dir에서 이 파일을 생성하려면 public 이여야지만 이 객체를 생성할 수 있다.

  1. public class의 이름과 java파일은 대소문자까지 같아야한다.

  2. public class는 하나의 java파일속에 하나만 존재할 수 있다.

    • 첫번째 문법적 사실과 모순되기 때문에
  3. 하나의 java파일에는 하나의 public class만 존재할 수 있고, class는 여러개 존재할 수 있다.

import orange.area.Circle;
import java.util.Scanner;
//import orange.perimeter.Circle; //이렇게 하면 오류 > class이름이 같아서 Circle이 두개니까 둘 중에 하나만 import가능
class CircleMain{

    public static void main(String[]args){

        orange.area.Circle c1 = new orange.area.Circle(5);
        System.out.println(c1.areaOfCircle());

        orange.perimeter.Circle c2 = new orange.perimeter.Circle(10);
        System.out.println(c2.perimeterOfCircle()); //이건 오류나는데 왜나지 몰름

        Circle c3 = new Circle(20); //orange.area.Circle을 import해서 이렇게 부르는게 가능
        System.out.println(c3.areaOfCircle());

        System.out.println(c3.areaOfCircle()); //import를 했으면 이렇게 사용
        //java.util.Scanner sc = new java.util.Scanner(System.in); 안하면 이렇게
    }
}
  • 아무것도 없이 class AAA만 있다면 java에서 자동으로 default지시자를 생성한다.

    • 해당 클래스 안 메소드가 public이여도 class가 default이기 때문에 제한이 걸리긴 한다.

    • class와 그 속에 있는 생성자의 접근제어는 같게하는게 좋다.

  • 위에는 파일 안에 이름이 Circle로 이름이 같아서 동시에 두개의 파일을 import해올 수 없는것이다.

각 다른 위치에 있는 하나의 코드들을 컴파일 할때
  • javac -d . Circle.java > 현재 디렉터리의 Circle.java를 컴파일하는데 컴파일하는 파일에 패키지가 있으면 패키지까지 컴파일해라 (없으면 java)

    • javac -d . *.java 사용할때 pause를 꼭 사용해야한다 cmd창 꺼진다.

test1 - 파일을 만들어서java파일과 그 파일 안에 만든 class파일을 생성하는것

test2 - .bat라는 배치파일을 이용해 class파일들을 이동시키고 class끼리 파일 위치는 다르지만 classpath를 잡아서 Main클래스가 동작하게 함

test3 - orange파일 안에 area파일을 만들어 원의 면적을 구하는 java파일을 만들고, orange파일 안에 perimeter파일을 만들어 원의 둘레를 구하는 java파일을 만든다 > 내가 오류난 이유는 java파일 안 class이름이 틀려서

test4 - class파일끼리 나뉘어서 그 안에 각각 넣을 package를 선언하고, 호출되는 것들은 import로 따로 선언해주고 각각 다른 위치에서 불러오기 때문에 class앞에 public을 꼭 붙여야한다.

저장 후 컴파일할때 java -d . (해당 클래스 파일명).java컴파일 해주면 package선언한 파일들이 생성되어 그 속에 자동 저장된다.

주의할 점은 호출한 파일들은 모두 import해야하는데(두개도 가능), import해올 파일의 이름이 같다면, 패키지까지 포함한 파일의 이름을 호출한곳을 수정해 넣어야한다.

test5 - test4와 마찬가지로 진행하고 배치프로그램을 만들어준다.


퀴즈 : FruitSalesMain3.java의

FruitSeller 클래스를 orange.seller 패키지에 묶어서 컴파일 하자.

FruitBuyer 클래스를 orange.buyer 패키지로 묶어 컴파일 하자

pckage는 문법적으로 제일 위에 import보다 위로

다른 곳을 호출한 곳이 있다면 import를 해오던가 풀네임으로 적어야한다.

  1. FruitSalesMain3.java를 가지고 와서 클래스끼리 다른 .java로 만든다.
  2. 각 클래스들을

캡슐화(Encapsulation)

연관된 목적을 가지는 변수와 함수를 하나의 클래스로 묶어 외부에서 쉽게 접근하지 못하도록 은닉하는 것이다.

정보 은닉 > 외부에서 내부의 정보에 접근하거나 변경할 수 없게 직접적인 접근 막는 역할

객체가 제공하는 필드와 메소드를 통해서만 접근 가능

접근제어 지시자

멤버변수에서만 사용

지역변수에 쓸 수는 없음 > 지역변수는 어차피 소멸되기 때문에

  • 아무것도 없이 class AAA만 있다면 java에서 자동으로 default지시자를 생성한다.

    • 해당 클래스 안 메소드가 public이여도 class가 default이기 때문에 제한이 걸리긴 한다.

    • class와 그 속에 있는 생성자의 접근제어는 같게하는게 좋다.

class Number{
    private int num1; //private는 클래스 내부에서만 접근 가
    int num2; //아무것도 쓰지 않은 것은 default 지시자다. 
    protected int num3; //num3는 클래스 내부, 동일 패키지, 상속받은 클래스에서만 접근 가능하다.
    public int num4; //num4 변수는 모든 영역에서 접근 가능하다.
}
class Number{
    private int num1; 
    int num2; 
    protected int um3; 
    public int num4;
}
class NumberMain{
    public static void main(String[]args){
        Number n1 = new Number();
        n1.num1 = 100; //접근 불가능 private은 동일 클래스 내에서만 가능해서
        n1.num2 = 100; // 접근 가능
class AAA{
    public AAA(){}
}
public class BBB{
    BBB(){}
}
  • AAA가 public이지만 class AAA가 default이기 때문에 클래스내부, 동일 패키지에서만 접근 가능하

퀴즈 - 접근제어자를 이용한 적절한 값을 입력받도록 유도하는 문제

class Rectangle
{
    int ulx, uly;        // 좌 상단 x, y 좌표
    int lrx, lry;        // 우 하단 x, y 좌표

    public void showArea()
    {
        int xLen = lrx-ulx;
        int yLen = lry-uly;
        System.out.println("넓이 : " + (xLen*yLen);
    }
}

class RectangleTest
{
    public static void main(String[] args)
    {
        Rectangle rec = new Rectangle();
        rec.ulx=22;
        rec.uly=22;
        rec.lrx=10;
        rec.lry=10;
        rec.showArea();
    }
}
  • 이 식을변형하여 문제 풀이 > 사용자가 입력한 값이 옳은지 옳지 않으면 옳지 않다고 출력까지

  • x좌표는 0이상 100이하의 범위를 갖는다. 오른쪽으로 이동할수록 값은 증가한다.

  • y좌표는 0이상 100이하의 범위를 갖는다. 아래로 이동할수록 값은 증가한다.

  • 우 하단의 x, y좌표 값이 좌 상단의 x, y 좌표값보다 작아서는 안된다.

정답
class Rectangle
{
    private int ulx, uly;        // 좌 상단 x, y 좌표
    private int lrx, lry;        // 우 하단 x, y 좌표

    private boolean isProperRange(int pos) //boolean자료형 변수에서 is 사용해서 자주 씀 
    {
        if(0<=pos && pos <= 100) //입력된 값이 0보다 크고 100보다 작은지 검증하는 메소드 
            return true;
        else
            return false;
    }
    public void setRectanglePoint(int lx, int ly, int rx, int ry) //입력받은 좌표값의 범위가 맞는지 확인하는 메소드
    {
        if(lx>=rx || ly>=ry)
        {
            System.out.println("좌표 지정이 잘못되었습니다.");
            return;
        }
        if( !isProperRange(lx) || !isProperRange(ly) )//범위가 맞게 되었는지 알아내는 if문
        {// 앞에 !하고 호출해도 호출 먼저 실행하고 값이 돌아온후 논리 not실행 
            System.out.println("좌 상단 좌표의 범위가 잘못되었습니다.");
            return;
        }
        if( !isProperRange(rx) || !isProperRange(ry) )
        {
            System.out.println("우 하단 좌표의 범위가 잘못되었습니다.");
            return;
        }

        ulx = lx; //초기화하지 않은 상태여서 0으로 출력
        uly = ly;
        lrx = rx;
        lry = ry;
    }

    public void showArea()
    {
        int xLen = lrx - ulx;
        int yLen = lry - uly;
        System.out.println("넓이 : " + (xLen*yLen) );
    }
}

class RectangleTest
{
    public static void main(String[] args)
    {
        Rectangle rec = new Rectangle(); //객체 생성 
        rec.setRectanglePoint(-3, -1, 2, 7); //좌상단 좌표의 범위가 잘못되었다 출력 
        rec.showArea();

        rec.setRectanglePoint(2, 2, 8, 8); //얘는 맞게 값이 들어가 36이 출력됌
        rec.showArea();
    }
}

다른 예제

package orange.cal;

public class Calculator
{
    private Adder adder;
    private Subtractor subtractor;

    public Calculator()
    {
        adder = new Adder();
        subtractor = new Subtractor();
    }
    public int addTwoNumber(int num1, int num2)
    {
        return adder.addTwoNumber(num1, num2);
    }
    public int subTwoNumber(int num1, int num2)
    {
        return subtractor.subTwoNumber(num1, num2);
    }
    public void showOperatingTimes()
    {
        System.out.println("덧셈 횟수: " + adder.getCntAdd());
        System.out.println("뺄셈 횟수 : " + subtractor.getCntSub());
    }
}
class Adder
{
    private int cntAdd;

    Adder() { cntAdd = 0; }
    int getCntAdd() { return cntAdd; }
    int addTwoNumber(int num1, int num2)
    {
        cntAdd++;
        return num1 + num2;
    }
}
class Subtractor
{
    private int cntSub;

    Subtractor() { cntSub = 0; }
    int getCntSub() { return cntSub; }
    int subTwoNumber(int num1, int num2)
    {
        cntSub++;
        return num1 - num2;
    }
}
class CalculatorMain
{
    public static void main(String[] args)
    {
        Calculator cal = new Calculator();
        System.out.println("1+2=" + cal.addTwoNumber(1, 2));
        System.out.println("2+4=" + cal.addTwoNumber(2, 4));
        System.out.println("5-1=" + cal.subTwoNumber(5, 1));

        cal.showOperatingTimes();
    }
}

  • 클래스를 작은 크기로 디자인하여 하나의 완성된 클래스로 묶는다면, 다음과 같은 이점이 생긴다.

    • 변경이 필요할 때, 변경되는 클래스의 범위를 최소화 할 수 있다.

    • 작은 크기의 클래스를 다른 클래스의 정의에도 활용할 수 있다.


다른 예제

class SinivelCap   // 콧물 처치용 캡슐
{
    public void take()
    {
        System.out.println("콧물이 싹~ 납니다.");
    }
}

class SneezeCap   // 재채기 처치용 캡슐
{
    public void take() 
    {
        System.out.println("재채기가 멎습니다.");
    }
}

class SnuffleCap   // 코막힘 처치용 캡슐
{
    public void take() 
     {
        System.out.println("코가 뻥 뚫립니다.");
    }
}

class ColdPatient//해당하는 take로 들어가 해당 출력값이 출력된다.
{
    public void takeSinivelCap(SinivelCap cap)
    {
        cap.take();
    }
    public void takeSneezeCap(SneezeCap cap)
    {
        cap.take();
    }
    public void takeSnuffleCap(SnuffleCap cap)
    {    
        cap.take();
    }
}

class Encapsulation1
{
    public static void main(String[] args)
    {
        ColdPatient sufferer = new ColdPatient();//suffer객체 생성 > takeSi, takeSne, takeSnu 메소드 들어가있음
        SinivelCap siCap = new SinivelCap(); //siCap객체 생성
        sufferer.takeSinivelCap(siCap);    //siCap객체 안에 takeSi메소드 

        sufferer.takeSinivelCap(new SinivelCap()); //이 문장은 참조변수 없이 객체를 생성해서 한번 쓰고 버리는
        sufferer.takeSneezeCap(new SneezeCap());//이 문장들은 객체 주소값을 저장하고 있는 주소변수가 없기 때문에 다시 참조할 수 없다.
        sufferer.takeSnuffleCap(new SnuffleCap());//그러므로 바로 coldpatient메소드로 올라가 해당하는 문장의 cap안에 들어가 넘겨주고 소멸된다.
    } 
}//이 문장들은 결국 순서가 정해져있다. 호출에 호출을 해서 약을 먹이는것이기 때문
위 코드에서 호출을 간단하게 해서 약 먹일 수 있도록
class SinivelCap   // 콧물 처치용 캡슐
{
    public void take(){System.out.println("콧물이 싹~ 납니다.");}
}

class SneezeCap   // 재채기 처치용 캡슐
{
    public void take() {System.out.println("재채기가 멎습니다.");}
}

class SnuffleCap   // 코막힘 처치용 캡슐
{
    public void take() {System.out.println("코가 뻥 뚫립니다.");}
}
///////////////////////////////////////////////

class CONTAC600     //캡슐화....
{
    SinivelCap sin;
    SneezeCap sne;
    SnuffleCap snu;

    public CONTAC600() //호출되면 바로 약먹도록 아래로 연결 
    {
        sin=new SinivelCap();
        sne=new SneezeCap();
        snu=new SnuffleCap();
    }
    public void take() //얘와 연결되는 
    {
        sin.take();
        sne.take();
        snu.take();
    }
}

class ColdPatient
{
    public void takeCONTAC600(CONTAC600 cap){cap.take();}
}

class Encapsulation2
{
    public static void main(String args[])
    {
        ColdPatient sufferer = new ColdPatient(); //객체 생성
        sufferer.takeCONTAC600(new CONTAC600()); 

    }
}

퀴즈 2 - 앞에 내용 응용 문제

class Point
{
    private int xPos, yPos;

    public Point(int x, int y)
    {
        xPos = x;
        yPos = y;
    }
    public void showPointInfo()
    {
        System.out.println("[" + xPos + ", " + yPos + "]");
    }
}
class MainClass
{
    public static void main(String[] args)
    {
        Ring ring = new Ring(1, 1, 4, 2, 2, 9);
        ring.showRingInfo();
    }
}

이 문장을 가지고 다음과 같은 출력 결과를 나오게 하시오

class Point x좌표와 y좌표를 나타낸다.
class Circle 중심좌표(x좌표와 y좌표)와 반지름의 값을 갖는다.
class Ring 안쪽원(Circle)과 바깥쪽원(Circle)로 이루어져 있다.

출력 결과
Inner Circle Info...
radius : 4
[1, 1]
Outer Circle Info...
radius : 9
[2, 2

내가 한 문장 - 하다가 만

class Point
{
    private int xPos, yPos;

    public Point(int x, int y)
    {
        xPos = x;
        yPos = y;
    }
    public void showPointInfo()
    {
        System.out.println("[" + xPos + ", " + yPos + "]");
    }
}
class Circle{

    private int radius, point1, point2;

    public Circle(Point point1, Point point2 ,int radius){
        this.point1 = point.Point(x);
        this.point2 = point.Point(y);
        this.radius = radius;
    }
    public void showCircleInfo(){

        System.out.println("radius : " + this.radius);
    }
}
class Ring{
    point po;
    Circle ci;

    public Ring(){
        po = new Point();
        ci = new Circle();
    }

    public void showRingInfo(

class MainClass
{
    public static void main(String[] args)
    {
        Ring ring = new Ring(1, 1, 4, 2, 2, 9);
        ring.showRingInfo();
    }
}
  • class Circle이 중심좌표와 반지름의 값을 갖는다 > 반지름을 멤버변수로 지정한것은 맞지만 중심좌표는 Point클래스에서 받아와야하기에 자료형을 Point로 두었어야했다.

  • Circle안에 생성자를 만들어, main 메소드에서 입력 받을 값의 변수를 정하고, 중심 좌표를 담을 객체를 생성하면서 호출을 한다.

정답

class Point
{
    private int xPos, yPos;

    public Point(int x, int y)
    {
        xPos = x;
        yPos = y;
    }
    public void showPointInfo()
    {
        System.out.println("[" + xPos + ", " + yPos + "]");
    }
}
class Circle
{
    private Point center;//point에서 중심좌표 가져와야하니까 자료형을 Point로 
    private int radius;
    Circle(int xPos, int yPos, int radius) 
//Circle의 생성자 > main에서 Ring을 호출하고 Ring에서 Circle을 호출해 값이 들어간
// 값을 받아와서 Point에 중심점을 넣어줘야하기 때문에 지역 변수 생성
    {
        center = new Point(xPos, yPos);
        this.radius = radius; //받아온 반지름 값을 해당 인스턴스에 저장 
    }
    public void showCircleInfo()
    {
        System.out.println("radius : " + radius);
        center.showPointInfo();//반지름 출력 후 중심좌표 출력해야하고 처음 중심좌표를 저장할 멤버변수를
                                //center로 했기때문에 center를 이용해 호출해준
    }
}

class Ring
{
    private Circle ic;
    private Circle oc;
    Ring(int iXPos, int iYPos, int iRadius, int oXPos, int oYPos, int oRadius)
    {
        ic = new Circle(iXPos, iYPos, iRadius); //Circle을 호출하면서 객체 생성 >1,1,4 삽입 
        oc = new Circle(oXPos, oYPos, oRadius); //객체 생성 > 2,2,9 삽입 
    }
    public void showRingInfo()
    {
        System.out.println("Inner Circle Info...");
        ic.showCircleInfo();
        System.out.println("Outer Circle Info...");
        oc.showCircleInfo();
    }
}
class MainClass
{
    public static void main(String[] args)
    {
        Ring ring = new Ring(1, 1, 4, 2, 2, 9); //Ring을 호출하면서 객체 생성 
        ring.showRingInfo();
    }
}
  • 처음 받은 양식을 보면 MainClass에서 Ring을 호출해 값을 넣기때문에 Ring클래스 안에 값을 받아서 각 객체를 만들어 안쪽원, 바깥쪽원으로 나누어 출력할 수 있도록 만든다.


클래스 내 Set, Get 메소드

set : 변수값을 할당하는 목적의 함수 > 인자를 받아야한다,

get : 변수값을 반환하는 목적으로 > return이 필요하다.

class Number{
    private int num1; 
    int num2; 
    protected int um3; 
    public int num4;
}
    public void printCS(){
        System.out.println(num1);
    }
    public int getNum1(){ 
    return num1;
    }
    public void setNum1(int num1){
        this.num1 = num1;
    }
}
class NumberMain{
    public static void main(String[]args){
        Number n1 = new Number();
        n1.num2 = 100; 
        System.out.pritnln(n1.getNum1());
        n1.setNum1(10);

0개의 댓글