스프링 부트 1주차 CRUD

결국엔 해냈습니다!!

물론.. 수업에서 실습한 코드를 베이스로 작성한 것이지만요.

오늘 구현한 기능은 아래와 같습니다.

  • 전체 게시글 수정 및 삭제: 제목, 작성자명, 작성 내용을 비밀번호를 일치 여부 확인 후 실행
  • 삭제 버튼 추가
  • 삭제 버튼 누르면 비밀번호 input 박스와 삭제 확인 버튼 생성

아래는 신나서 만든 시현 영상입니다.

 

 

 

  • 그냥 비밀번호만 확인한다고 해도 앞에 ${id}-변수 값을 넣어줘서 해당 id에 붙도록 해야 합니다.

비밀번호 확인을 서버에서 하는데 아래 코드를 썼습니다.

 

 //비밀번호 확인하기
    @PutMapping("/api/memos/{id}")
    public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
        Memo memo = memoRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("아이디가 존재하지 않습니다.")
        );
        if (memo.getPassword().equals(requestDto.getPassword())) {
            memoService.update(id, requestDto);
            return id;
        } else return 0L;
    }

    @DeleteMapping("/api/memos/{id}")
    public Long deleteMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
        Memo memo = memoRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("아이디가 존재하지 않습니다.")
        );

        if (memo.getPassword().equals(requestDto.getPassword())) {
            memoService.deleteMemo(id);
            return id;
        } else return 0L;
    }
}

 

자바랑 Spring 공부 좀 하다가 최종 제출 전에 암호화를 한 번 해보려고 합니다.

그리고 날짜 포맷 바꾸는 것도 할 수 있으면 해보려고 합니다.

 

이번주가 주특기 1주차인데 벌써 공부할 게 산더미처럼 쌓였습니다.

김영한님의 스프링 강의를 추천받았습니다.

우선 내일은 자바의 정석 7강부터 듣고 혼공자 언어스터디 분량 공부하고 오후 쯤 스프링 강의 구매를 하려고 합니다.

 

 

 

GitHub - sooni2/Spring_study: for studying java Spring

for studying java Spring. Contribute to sooni2/Spring_study development by creating an account on GitHub.

github.com

아직 main에 머지는 안했습니다.

 

 

 

Spring Java Study

JPA 연습

각 데이터 별로 Entity와 Repository를 만들었습니다.

아래처럼 localhost:8080/h2-console 을 입력해서 브라우저에서도 JPA 가 잘 작동하는지 확인했습니다.

JPA H2 console

 

 

상속을 사용해서 생성 수정 시간 관리하기

1. Timestamped 객체를 생성한다.

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class) 
public class Timestamped {

    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column
    private LocalDateTime modifiedAt;
}

2. extends로 상속 받아서 사용 한다.

@Entity // 게시글
public class Post extends Timestamped {
	  @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false, unique = true)
    private String content;
}

 

@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;

@LastModifiedDate
@Column
private LocalDateTime modifiedAt;
  • “extends Timestamped” 으로 상속받는 객체들은 자동으로 생성, 수정시간을 데이터베이스에 입력
  • 필요하다면 해당값을 편하게 Get 할수 있음

 

Spring Data JPA

  • JPA 를 편리하게 사용하기 위해, 스프링에서 JPA 를 Wrapping 함
  • 스프링 개발자들이 JPA 를 사용할 때 필수적으로 생성해야 하나, 예상 가능하고 반복적인 코드들 → Spring Data JPA 가 대신 작성
  • Repostiory 인터페이스만 작성하면, 필요한 구현은 스프링이 대신 함

공식문서

 

Spring Data JPA - Reference Documentation

Example 119. Using @Transactional at query methods @Transactional(readOnly = true) interface UserRepository extends JpaRepository { List findByLastname(String lastname); @Modifying @Transactional @Query("delete from User u where u.active = false") void del

docs.spring.io

 

메모장 사이트 만들기

  • readOnly 메서드가 추가가 안되서 구글링했더니 아래와 같이 org.springframework.transaction.annotation.Transactional 을 해야하는 거였습니다. 
  • 자동으로 해당 패키지가 import되어서 앞부분 다시 지우고 @Transactional 만 넣어줬습니다.

 

 

The attribute readOnly is undefined for the annotation type Transactional

I am getting this error when I am putting this piece of code on a service method @Transactional(readOnly =true) I am writing this code to make a transaction read only. Can you please tell me Wh...

stackoverflow.com

 

이미지 깨짐 현상

아래처럼 static.images에 넣어준 이미지들이 깨진 것을 확인하고 문제 해결을 위해 구글링을 하고 슬랙에 질문을 했습니다.

스프링 이미지 깨짐

경로 설정이 잘못되었던 것이었습니다...

강의에서 static.images 파일에 이미지 저장하라고 해서 했는데

static 파일안에 images 파일을 만들어서 저장하라는 말이었습니다.

 

이럴수가.

 

 

개인 과제

유스케이스(usecase) 만들기

- 관련 자료

 

유스케이스

주어진 자료를 바탕으로 유스케이스 작성을 해보았습니다.

 

 

이게 맞아....??

 

일단 수업에서 한 실습 자료를 바탕으로 기능 추가 구현을 해보도록 하겠습니다.

혼자공부하는자바 패키지와 접근제한자

 

  • 패키지: 파일 시스템의 폴더 기능 + 클래스를 유일하게 만들어주는 식별자 
  • 패키지가 다르면 클래스 이름이 동일해도 다른 클래스로 인식

 

상위패키지.하위패키지.클래스

 

패키지 선언

package 상위패키지.하위패키지;

public class ClassName{ ... }
  • 패키지는 클래스의 일부
  • 패키지 이름
    • 숫자로 시작해서는 안되고 _, $를 제외한 특수 문자 사용 x
    • java로 시작하는 패키지는 자바 표준 API에서만 사용하므로 사용 x
    • 모두 소문자로 작성하는 것이 관례

 

import문

  • import문으로 해당 패키지의 클래스 또는 인터페이스를 가져와 사용할 것을 컴파일러에게 알려줌

 

import 상위패키지.하위패키지.클래스이름;

import 상위패키지.하위패키지.*;

 

  • *를 이용해서 해당 패키지에 소속된 클래스들을 사용할 것을 알려줌
  • import문은 개수에 제한이 없음
  • 상위 패키지를 import했다고 하위까지 import되는 것은 아님

 

 

접근 제한자(Access Modifier)

  • public : 외부 클래스가 자요롭게 사용
  • protected: 같은 패키지 또는 자식 클래스에서 사용할수 있음
  • private: 외부에서 사용 x
  • default: 같은 패키지에 소속된 클래스에서만 사용

 

클래스의 접근 제한

//defalut 접근 제함

class 클래스 { ... }



//public 접근 제한

public class 클래스 { ... }

public 접근 제한

  • 클래스를 다른 개발자가 사용할수 있도록 라이브러리 클래스로 개발한다면 반드시 public 접근 제한을 갖도록 해야함
  • 인터넷으로 배포되는 라이브러리 클래스도 모두 public 접근 제한을 가지고 있음

 

생성자의 접근 제한

  • public 접근 제한: 모든 패키지에서 제한없이 생성자 호출
  • protected 접근 제한 : 같은 패키지에 속하는 클래스에서 생성자 호출 가능; 다른 패키지여도 해당 클래스의 자식클래스라면 생성자호출가능
  • default 접근 제한: 같은 패키지 내에 제한없이 생성자 호출 가능
  • private 접근 제한: 오직 클래스 내부에서만 생성자 호출하고 객체를 만들수 있음

 

필드와 메소드의 접근 제한

//필드 선언

[public | protected | private ] [static] 타입 필드;



/메소드 선언

[public | protected | private ] [static] 리턴 타입 메소드(..) { ... }

 

  • public : 제한 없음
  • protected: 다른 패키지에 속하는 클래스에서 필드와 메소드를 사용가능; 다른 패키지 클래스가 자식 클래스라명 사용 가능
  • default: 같은 패키지 제한 없고 다른패키지 x
  • private: 오직 클래스 내부에서만 사용

 

Getter와 Setter 메소드

  • 일반적으로 객체 지향 프로그래밍에서는 객체의 필드를 객체 외부에서 직접적으로 접근하는 것을 막는다
  • 외부에서 마음대로 변경할 경우 객체의 무결성이 깨질 수 있기 때문
  • 메소드를 필드를 변경하는 방법을 선호
  • 필드는 외부에서 접근할 수 없도록 막고 메소드는 공개해서 외부에서 메소드를 통해 필드에 접근하도록 유도
  • 메소드는 매개값을 검증해서 유효한 값만 객체의 필드로 저장할 수 있기 때문 -> Setter
  • 외부에서 객체의 데이터를 읽을 때도 메소드를 사용 -> Getter
  • 클래스를 선언할 때 가능하다면 필드를 private으로 선언해서 외부로부터 보호하고 필드에 대한 Setter와 Getter 메소드를 작성해서 필드값을 안전하게 변경/사용
  • Getter: 필드의 값을 외부로 리턴해주는 메소드
  • Setter: 외부에서 값을 받아 필드를 변경하는 메소드

 

Getter와 Setter

  • 외부에서 필드값 read only로 하려면 Getter 메소드만 선언 또는 Setter 메소드에 private 접근 제한 선언

 

 

확인문제

  • 접근 제한자는 클래스, 필드, 생성자, 메소드의 사용을 제한한다. (o)
  • public 접근 제한은 아무런 제한 없이 해당 요소를 사용할 수 있게 한다. (o)
  • default 접근 제한은 해다 클래스 내부에서만 사용을 허가한다. (x)
  • 외부에서 접근하지 못하도록 하려면 private 접근 제한을 해야 한다. (o)

 

 

 

 

 

 

혼자공부하는자바 인스턴스 멤버와 정적 멤버

 

  • 클래스 멤버를 인스턴스 멤버와 정적 멤버로 구분해서 선언할 수 있음
  • 인스턴스 멤버: 객체마다 가지고 있는 멤버
  • 정적 멤버: 클래스에 위치시키고 객체들이 공유하는 멤버

 

인스턴스 멤버와 this

  • 인스턴스 멤버: 객체(인스턴스)를 생성한 후 사용할 수 있는 필드와 메소드
  • 인스턴스 멤버 선언
public class Car {

//필드

int gas;



//메소드

void set Speed(int speed) {....}

}
  • 메모리 블록 내부에 인스턴스 필드 등이 사용되는 경우가 있음
  • 인스턴스 필드가 사용되면 메소드는 객체 없이 실행할 수 없음

 

 

this

  • 객체 내부에서 인스턴스 멤버에 접근하기 위해 this를 사용
  • 객체는 자신을 this라고 함
  • 주로 생성자와 메소드의 매개 변수 이름이 필드와 동일한 경우, 인스턴스 멤버인 필드임을 명시할 때 사용

 

정적 멤버와 static

  • 정적 멤버: 클래스에 고정된 멤버로 객체를 생성하지 않고 사용할 수 있는 필드와 메소드
  • 정적 멤버 선언 -> static 키워드를 추가적으로 붙이면 됨
public class 클래스 {

//정적 필드

static 타입 필드 [=초기값];



//정적 메소드

static 리턴 타입 메소드( 매개변수선언, ...) {...}

}

 

  • 클래스에 고정된 멤버로 클래스 로더가 클래스(바이트 코드)를 코딩해서 메소드 메모리 영역에 적재할 때 클래스별로 관리
  • 객체마다 가지고 있어야 할 데이터라면 인스턴스 필드로 선언
  • 객체마다 가지고 있을 필요가 없는 공용 데이터라면 정적 필드로 선언

 

정적 멤버 사용

  • 클래스 이름과 함께 도트(.) 연산자로 접근
클래스.필드;

클래스.메소드(매개값, ...);

 

정적 메소드 선언 시 주의할 점

  • 정적 메소드를 선언할 때는 내부에 인스턴스 필드나 인스턴스 메소드를 사용할 수 없음
  • this 키워드도 사용 불가능
  • 정적 메소드에서 인스턴스 멤버를 사용하고 싶다면 객체를 먼저 생성하고 참조 변수로 접근

 

싱글톤(Singleton)

  • 전체 프로그램에서 단 하나의 객체만 만들도록 보장해야 하는 경우
  • 클래스 외부에서 new 연산자로 생성자를 호출할 수 없도록 막아야 함 -> private 접근 제한자 붙이기
  • 자신의 타입인 정적 필드를 선언하고 자신의 객체를 생성해 초기화
  • 외부에서 호출할 수 있는 정적 메소드 getInstance() 선언하고 정적 필드에서 참조하고 있는 자신의 객체를 리턴

 

public class 클래스 {

//정적 필드

private static 클래스 singleton = new 클래스();



//생성자

private 클래스() {}



//정적 메소드

static 클래스 getInstance() {

   return singleton;

}

}

 

  • 외부에서 객체를 얻는 유일한 방법은 getInstance() 메소드를 호출하는 방법 -> 단 하나의 객체만 리턴

 

final 필드와 상수

  • final 필드: 초기값이 최종적인 값이 되어서 프로그램 실행 도중에 수정할 수 없음
final 타입 필드 [=초기값];
  • final 필드의 초기값을 주는 방법
    • 필드 선언시 주는 방법
    • 생성자에서 주는 방법

 

상수 constant

  • final 필드는 상수가 아님 
  • 객체마다 저장되고, 생성자의 매개값을 통해서 여러 가지 값을 가질 수 있기 때문에 상수 x
  • 상수는 static이면서 final 이어야함

 

static final 타입 상수= 초기값;
  • 상수 이름은 모두 대문자로 작성
  • 혼합된이름은 (_)로 연결

 

확인문제

  • 정적 멤버는 static으로 선언된 필드와 메소드를 말한다 (o)
  • 인스턴스 필드는 생성자에서 초기화될 수 없다.(x)
  • 정적 필드와 메소드는 객체 생성 없이 클래스를 통해 접근할 수 있다. (o)
  • 인스턴스 필드와 메소드는 객체를 생성하고 사용해야 한다 (o)
  • final 필드와 상수는 초기값이 저장되면 값을 변경할 수 없다 (o)
  • final 필드와 상수는 생성자에서 초기화 될 수 있다. (x)
  • 상수의 이름은 대문자로 작성하는 것이 관례이다 (o)
  • 상수는 객체 생성없이 클래스를 통해 사용할 수 있다 (o)

2주차

벌써 부트캠프를 정식으로 시작한지 2주가 지났습니다. pre-onboarding 주차까지 합치면 3주가 흘렀습니다.

 

이번주는 객체지향언어인 자바에 대해 더 알아가는 시간을 가졌습니다. 이제 시작한 초짜인 저는 걷기반에 들어가 알고리즘 공부를 하면서 자바 문법과 다양한 메소드를 알게 되었습니다. 따로 자바에 대한 공부를 하라고 하지는 않았지만 남궁성의 자바의 정석 유튜브 강의를 챕터 6까지 들었습니다.

 

 

'부트캠프/자바의 정석' 카테고리의 글 목록

프로 개발자가 되기 위한 핏짜의 항해 기록

pizzathedeveloper.tistory.com

 

객체지향언어로 각각 객체, 메소드를 따로 만들고 필요할 때마다 불러서 쓰는 개념에 대해 배웠는데 금요일에 제출해야했던 SA 과제는 좀 버겁긴 했습니다. 생각대로 작동이 안되서 다시 한번 손 볼 필요가 있습니다.

 

 

TIL 221125 객체지향 과제

생각대로 되지는 않았고 고쳐야 하는 곳이 많지만 일단은 이렇게 올렸습니다. 버스 정원이 왜 저따구로 되는지 모르겠지만 다시 고치러 돌아오도록하겠습니다. 일단 Spring이랑 자바 강의부터 마

pizzathedeveloper.tistory.com

 

Spring boot 시작

아직 객체 지향을 완벽히 다룰 수가 없는데 스프링을 시작하려니 머리가 아픕니다.

아직까지는 강의 코드를 복붙하고 있는데 본격적으로 프로젝트를 들어가기 전에 자바를 많이 공부해야할 듯 합니다. 자바 공부를 하는 시간이 커리큘럼에 더 많이 배정되면 어땠을까 하는 아쉬움이 있습니다. 이제 ABCD를 배우고 있는데 갑자기 영어로 레포트 쓰라고 하는 느낌입니다.

 

 

 

TIL Spring boot 1주차 javax 에서 jakarta로 업데이트 221126

항해99에서 제공해주는 강의는 기초적인 내용은 겉햟기로 지나가는 경우가 많은 것 같다. 시간을 들여서 깊이 공부해야하는 부분을 하면서 "마! 알아서 익혀라!"라는 식이거나 "마! 이미 너는 알

pizzathedeveloper.tistory.com

 

생각보다 시간이 빨리가는 느낌입니다. 이제 연말이라 한해의 끝이 다가오는데 연말 분위기에 휩쓸리지 않고 월드컵에도 휩쓸리지 말고 집중해서 개발자가 되는 것에 최선을 다하려고 합니다. 

 

같은 관심사와 목표를 공유하는 좋은 조원들을 많이 알게 되서 기분 좋은 한주 였습니다. 

 

항해99에서 제공해주는 강의는 기초적인 내용은 겉햟기로 지나가는 경우가 많은 것 같다. 시간을 들여서 깊이 공부해야하는 부분을 하면서 "마! 알아서 익혀라!"라는 식이거나 "마! 이미 너는 알고 있을 거다!"라고 하고 진행되는 부분이 상당히 있다. 다행히 나는 공부를 더 많이 하는 거에 대해서는 불만이 없지만 빨리 진도를 따라가야 하는 것에 대해서는 조금 압박이 있긴 하다. 그래도 새로운 것을 배우는 것은 늘 신나는 일이다. 규칙을 알면 간단한데 모르는 규칙이 많아서 얼렁뚱땅하다 보니 에러가 나는듯하다. 규칙을 알게 되서 나오는 "Ah-ha!" 모먼트가 많다.

주특기는 Spring

어제 드디어 Spring 강의가 지급되었고 본격적인 주특기 주차가 시작되었다. 아직 객체지향이라는 개념이 어색한데 SQL 배우는 중입니다.

 

ERD 예시

오늘의 Error

javax가 안뜨고 jakarta가 뜨길래 무슨 오류인가 했더니 Spring 3.0버전 부터는 jakarta로 업그레이드 되었다고 합니다.

관련 문서: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes

 

GitHub - spring-projects/spring-boot: Spring Boot

Spring Boot. Contribute to spring-projects/spring-boot development by creating an account on GitHub.

github.com

 

Jakarta

 

 

자바의 정석 기초편

접근 제어자(access modifier)

  • private: 같은 클래스 내에서만 접근이 가능
  • (default): 같은 패키지 내에서만 접근이 가능
  • protected: 같은 패키지 내에서, 그리고 다른 패키지의 자손클래스에서 접근이 가능
  • public: 접근 제한이 전혀 없음
  • public > protected > (default) > private

 

캡슐화와 접근 제어자

 

 

  • 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서

class Time{
    private int hour; //0~23 사이의 값을 가져야 함.
    private int minute;
    private int second;


    public void setHour(int hour){
        if(isValidhour(hour)) return;
        this.hour = hour;
    }

    //매개 변수로 넘겨진 hour가 유효한지 확인해서 알려주는 메서드
    private boolean isValidhour(int hour){
        return hour <0 || hour >23;
    }

    public int getHour() { return hour; };
}


public class TimeTest {
    public static void main(String[] args) {
        Time t = new Time();
//        t.hour = -100;
        t.setHour(21); //hour의 값을 21로 변경
        System.out.println(t.getHour());
        t.setHour(100);
        System.out.println(t.getHour());

    }
}

 

  • 접근제어자의 범위는 최소화 시키는 것이 좋다

다형성(polymorphism)

  • 여러가지 형태를 가질 수 있는 능력
  • 조상 타입 참조 변수로 자손 타입 객체를 다루는 것
  • 타입 불일치해도 괜찮다
  • 객체와 참조변수의 타입이 일치할 때와 일치하지 않을 때의 차이
  • 자손 타입의 참조변수로 조상 타입의 객체를 가리킬 수 없음
  • 참조변수의 타입은 인스턴스의 타입과 일치하는 것이 보통이지만 일치 하지 않을 수도 있음
  • 참조변수가 조상타입일 때와 자손 타입일 때의 차이
    • 참조변수로 사용할 수 있는 멤버의 갯수가 달라짐
  • 자손타입의 참조변수로 조상 타입의 객체를 가리킬 수 없음

 

참조변수의 형변환

  • 사용할 수 있는 멤버의 갯수를 조절하는 것
  • 조상 자손 관계의 참조변수는 서로 형변환 가능
  •  
public class Ex7_7 {
    public static void main(String[] args) {
        Car car = null;
        FireEngine fe = new FireEngine();
//        FireEngine fe2 = null; //car = (Car)fe; 에서 형변환이 생략됨

        FireEngine fe2 = (FireEngine)car; // 조상 -> 자손으로 형변환
        Car car2 = (Car)fe2;              // 자손 -> 조상으로 형변환
//        car2.drive(); //NullPointerException 발생.
//        fe.water();
//        fe2 = (FireEngine) fe; //자손타입 <- 조상타입, 형변환 생략 불가
//        fe2.water();
    }
}

class Car{
    String color;
    int door;

    void drive() {
        System.out.println("drive, Brrrr~~");
    }

    void stop() {
        System.out.println("stop!!");
    }
}

class FireEngine extends Car {
    FireEngine() {
    }

    void water() {
        System.out.println("water!!!");
    }
}



자바의 정석 기초편

패키지(package)

  • 서로 관련된 클래스의 묶음 (Java8 기준 약 4000개 클래스)
  • 클래스는 클래스 파일(*.class), 패키지는 폴더, 하위 패키지는 하위 폴더
  • 클래스의 실제 이름(full name)은 패키지를 포함(java.lang.String)
  • rt.jar는 클래스들을 압축한 파일 (rt = runtime)

 

패키지의 선언

  • 패키지는 소스파일의 첫번째 문장으로 단 한번 선언
  • 같은 소스 파일의 클래스들은 모두 같은 패키지에 속하게 된다
  • 패키지 선언이 없으면 이름없는(unnamed) 패키지에 속하게 된다

 

클래스 패스(classpath)

  • 클래스 파일(*.class)의 위치를 알려주는 경로 (path)
  • 환경변수 classpath로 관리하며, 경로간의 구분자는 ';'를 사용
  • classpath(환경변수)에 패키지의 루트를 등록해줘야 함

 

import문

  • 클래스를 사용할 때 패키지 이름을 생략할 수 있다.
  • 컴파일러에게 클래스가 속한 패키지를 알려준다
  • java.lang(자바의 기본패키지)의 클래스는 Import하지 않고도 사용할 수 있다.
    • String, Object, System, Thread ...

 

import문의 선언

  • import문을 선언하는 방법
    • import 패키지명.클래스명;
    • import 패키지명.*;
  • imprt문은 패키지문과 클래스 선언 사이에 선언

import문의 선언

  • 이름이 같은 클래스가 속한 두 패키지를 import할 때는 클래스 앞에 패키지 명을 붙여줘야 한다

 

static import문

  • static 멤버를 사용할 때 클래스 이름을 생략할 수 있게 해준다

static import문

 제어자(modifier)

  • 클래스와 클래스의 멤버(멤버 변수, 메서드)에 부가적인 의미 부여
  • 접근 제어자 public, protected, (default), private
  • 그 외: static, final, abstract, native, transient, synchronized, volatiled, strictfp
  • 하나의 대상에 여러 제어자를 같이 사용 가능(접근제어자는 하나만)

 

static -클래스의, 공통적인

 

static

 

final - 마지막의, 변경될 수 없는

  • 부모가 될 수 없는 마지막 클래스 final

final

 

abstract - 추상의, 미완성의

  • 미완성 설계도 -> 제품생산불가
  • 추상클래스를 상속받아서 완전한 클래스로 만들고 객체 생성가능

abstract

 

자바의 정석 상속

상속(Inheritance)

  • 기존의 클래스로 새로운 클래스를 작성하는 것 (코드의 재사용)
  • 두 클래스를 부모와 자식으로 관계를 맺어주는 것

 

class Parent{}
class Child extends Parent{
...
}
  • 자손은 조상의 모든 멤버를 상속받는다.(생성자, 초기화블럭 제외)
  • 자손의 멤버 개수는 조상보다 적을 수 없다(같거나 많다)

상속

  • 자손의 변경은 조상에 영향을 미치지 않는다.

 

 

포함 관계 

 

  • composite(포함): 클래스의 멤버로 참조변수를 선언하는 것
  • 상속관계 '~은 ~이다.(is-a)'
  • 포함관계 '~은 ~을 가지고 있다.(has-a)' ->대부분 포함관계를 씀

 

클래스 간의 관계 설정하기

class MyPoint{
    int x;
    int y;
}

//class Circle extends MyPoint { //상속
//    int r;
//}

class Circle {
    MyPoint p = new MyPoint();
    int r;
}


public class InheritanceTest {
    public static void main(String[] args) {

        Circle c = new Circle();
        c.p.x =1;
        c.p.y =2;
        c.r = 3;
        System.out.println("c.p.x="+c.p.x);
        System.out.println("c.p.y="+c.p.y);
        System.out.println("c.r="+c.r);
    }

}

 

단일 상속(Single Inheritance)

  • Java는 단일 상속만을 허용한다.
  • 조상은 하나만!
  • 비중이 높은 클래스 하나만 상속관계로, 나머지는 포함관계로 한다.

Object클래스 - 모든 클래스의 조상

  • 부모가 없는 클래스는 자동적으로 Object 클래스를 상속받게 된다.
  • 모든 클래스는 Object에 정의된 11개의 메서드를 상속받는다 (toString(), equals(), hashCode(),...)

 

public class InheritanceTest {
    public static void main(String[] args) {

        Circle c = new Circle();
        System.out.println(c.toString()); //Circle@340f438e
        Circle c2 = new Circle();
        System.out.println(c2.toString()); //Circle@30c7da1e
    }

}
  • toString()을 안써도 똑같이 출력된다.
  • println()의 기능

 

오버라이딩(overriding)

  • 상속받은 조상의 메서드를 자신에 맞게 변경하는 것
  • 선언부는 변경 불가, 내용만 변경가능

오버라이딩

class Point {
    int x;
    int y;
    String getLocation(){
        return "x: "+ x + ", y:" +y;
    }
}

class MyPoint3 extends Point {
    int z;
    //조상의 getLocation()을 오버라이딩
    String getLocation(){
        return "x: "+ x + ", y:" +y+" ,z:"+z;
    }

}

public class OverrideTest {
    public static void main(String[] args) {
        MyPoint3 p = new MyPoint3();
        p.x = 3;
        p.y =5;
        p.z =7;
        System.out.println(p.getLocation());
    }
}

 

오버라이딩의 조건

  • 선언부가 조상 클래스의 메서드와 일치해야 한다.
  • 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
  • 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.

 

오버로딩 vs 오버라이딩

근본적으로 관계 없음

overloading : 기존에 없는 새로운 메서드를 정의하는 것 (new)

overriding: 상속받은 메서드의 내용을 변경하는 것 

 

 

참조변수 super

  • 객체 자신을 가리키는 참조변수, 인스턴스 메서드(생성자)내에만 존재
  • 조상의 멤버를 자신의 멤버와 구별할 때 사용

super() - 조상의 생성자

  • 조상의 생성자를 호출할 때 사용
  • 조상의 멤버는 조상의 생성자를 호출해서 초기화

조상의 생성자

  • 클래스 이름 대신 super를 사용
  • 생성자의 첫 줄에 반드시 생성자를 호출해야 한다.
  • 그렇지 않으면 생성자의 첫 줄에 super();를 삽입한다.(조상의 기본 생성자)

 

 

생각대로 되지는 않았고

고쳐야 하는 곳이 많지만 일단은 이렇게 올렸습니다.

버스 정원이 왜 저따구로 되는지 모르겠지만 다시 고치러 돌아오도록하겠습니다.

일단 Spring이랑 자바 강의부터 마스터하러 갑니다...

 

Transport

public class transport { //상위 클래스 대중교통

    String number; //번호
    int gas = 100; //주유량: 주어진 기본값
    int speed = 0; //속도: 주어진 기본값
    int speedChange; //속도 변경
    String status = ""; //주행 상태
    int passengerMax; //최대 승객 수
    int fee; //요금



    //getter, setter

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public int getGas(int i) {
        return gas;
    }

    public int setGas(int gas) {
        this.gas = gas;
        return gas;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getSpeedChange() {
        return speedChange;
    }

    public void setSpeedChange(int speedChange) {
        this.speedChange = speedChange;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public int getPassengerMax() {
        return passengerMax;
    }

    public void setPassengerMax(int passengerMax) {
        this.passengerMax = passengerMax;
    }

    public int getFee(int now2) {
        return fee;
    }

    public void setFee(int fee) {
        this.fee = fee;
    }



    //메서드

    //운행 시작
    public void start(){
        System.out.println("운행 시작");
    }

    //속도 변경
    public int changeSpeed(int change){
        this.speedChange = change;
        return change;
    }

    //상태 변경
    public String statuschange(String statusChange){
        this.status = statusChange;
        return statusChange;
    }

    //max passenger call
    public int callPassengerMax(){
        return passengerMax;
    }

    //주유 하기
    public int addgas(int addgas){
        return this.gas += addgas;

    }










}

Bus

public class Bus extends transport{

    int passengerNow=0; //현재 승객 수

    Bus() {}; //기본 생성자 선언



    //getter, setter
    public int getPassengerNow() {
        return passengerNow;
    }

    public int setPassengerNow(int passengerNow) {
        this.passengerNow = passengerNow;
        return passengerNow;
    }



    //승객 탑승 가능 여부
    public boolean boardingcheck(){
        return super.callPassengerMax() >= passengerNow;
    }

    //승객수 추가


    //승객 탑승
    //탑승가능체크도 다 따로 케이스 만들어서 해보자
    public int boarding(int passenger) {


        if ((passengerNow += passenger)<= super.callPassengerMax()){
            if (status.equals("운행중")) {

                System.out.println("승객 " + passenger + "명이 탑승하였습니다");
                System.out.println("총 탑승 승객: " + this.passengerNow + "명");
            }


        } else {
        System.out.println("정원이 초과되었습니다.");
        }
    return this.passengerNow;
    }





    // 잔여 승객 수
    public int available(int passengerNow){
        return super.callPassengerMax()-this.passengerNow;
    }

    //버스 요금
    public int busfee(int passengers){
        return this.fee = (passengers*1000);
    }




    //주유 알람
    //연료가 10이상일때 운행 가능
    boolean leftFuel() {
        return this.gas >= 10;
    }

    boolean isRunning() {

        if(!status.equals("운행중")){  //운행 종료 시 차고지행
            super.setStatus("차고지행");
        }

        if(leftFuel()) {    //운행중 연료 체크
            System.out.println("주유량이 " +this.gas + " 남았습니다." );
            return true;
        }

        if(!leftFuel()) {   //주유량이 떨어지면 차고지행
            System.out.println("주유가 필요합니다.");  //경고메세지
            super.setStatus("차고지행");
        }

        return true;
    }

    //속도 변경
    public int speedChange(int speedChange){
        if(leftFuel()){
            speed += speedChange;
        }
        System.out.println("현재 주행속도는 "+speed+"km/hr 입니다.");
        return speed;
        }











}

Taxi

public class Taxi extends transport {

    String destination="";
    int basicDistance;
    int distancetoDes;

    int basicfee =3000; //기본요금

    int passengerNow;

    Taxi() {};

    Taxi(
            String number,
            int gas,
            int speed,
            String destination,
            int basicDistance,
            int distancetoDes,
            int fee,
            int basicfee,
            int passengerMax,
            String status,
            int passengerNow

    ){
        this.number =number;
        this.gas = 100;
        this.speed = 0;
        this.destination = destination;
        this.basicDistance =1000;
        this.distancetoDes = distancetoDes;
        this.fee = 1000;
        this.basicfee = basicfee;
        this.status = "일반";
        this.passengerMax = 4;
        this.passengerNow = passengerNow;

    }

    //getter setter


    public String getDestination() {
        return destination;
    }

    public void setDestination(String destination) {
        this.destination = destination;
    }

    public int getBasicDistance() {
        return basicDistance;
    }

    public void setBasicDistance(int basicDistance) {
        this.basicDistance = basicDistance;
    }

    public int getDistancetoDes() {
        return distancetoDes;
    }

    public void setDistancetoDes(int distancetoDes) {
        this.distancetoDes = distancetoDes;
    }

    public int getBasicfee() {
        return basicfee;
    }

    public void setBasicfee(int basicfee) {
        this.basicfee = basicfee;
    }

    public int getPassengerNow() {
        return passengerNow;
    }

    public void setPassengerNow(int passengerNow) {
        this.passengerNow = passengerNow;
    }



    //메서드

    //택시 요금 계산
    public int finalFee(int distancetoDes){
        int finalFee = basicfee+fee*(distancetoDes-basicDistance);
        System.out.println("최종 요금은 "+finalFee+"입니다.");
        return finalFee;
    }

    //탑승 가능 여부
    public boolean boardingcheck(){
        return passengerNow==0;
    }

    //승객수 추가
    public int addPassenger(int addPassenger){
        this.passengerNow += addPassenger;
        return this.passengerNow;
    }

    //승객 탑승
    public int boarding(int passenger){
        while(boardingcheck()){
            if(status.equals("운행")){
                System.out.println("승객"+addPassenger(passenger)+"명이 탑승하였습니다");
                System.out.println("총 탑승승객: "+passengerNow+"명");
                super.setStatus("운행 중");
            }
            break;
        }
        if(!boardingcheck()){
            int overPassenger = (addPassenger(passenger)+passengerNow)-passengerMax;
            System.out.println(overPassenger+"명 초과");
            System.out.println("탑승 불가");
            super.setStatus("탑승 불가");
        }
        return passengerNow;
    }

}

Operation

import java.util.Scanner;

public class Operation {
    public static void main(String[] args) {


        Scanner scanner = new Scanner(System.in);

        System.out.println("이동수단을 선택해주세요.");
        System.out.println("1. 택시 타기");
        System.out.println("2. 버스 타기");
        System.out.print("선택 >>");

        int option =0;
        option = scanner.nextInt();


        while(true){

            if(option==2){

                Bus bus1 = new Bus(); //새로운 버스 1
                bus1.setNumber("항해99");
                String bus1Number = bus1.getNumber();

                Bus bus2 = new Bus(); //새로운 버스 2
                bus2.setNumber("헤엘666");
                String bus2Number = bus2.getNumber();

                System.out.println("버스 2대 중 선택해주세요.");
                System.out.println("1. 항해99");
                System.out.println("2. 헤엘666");

                int option2 =0;
                option2 = scanner.nextInt();



                if(option2==1){
                        int passnum1 = bus1.getPassengerNow();
                        bus1.setPassengerMax(30);
                        bus1.setStatus("운행중");
                        int pass1 = 2;
                        bus1.boarding(pass1);
                        int passengerNow = bus1.getPassengerNow();
                        System.out.println("잔여 승객 수는 "+ bus1.available(pass1)+"명 입니다.");

                        int busfee1 = bus1.busfee(pass1);
                        System.out.println("버스 요금은 "+busfee1+"원 입니다.");
                    System.out.println();
                    System.out.println();

                    System.out.println("버스 기사가 주유량을 체크합니다.");

                    int gas1 = bus1.setGas(50);
                    bus1.isRunning();

                    System.out.println("버스 기사가 차고지로 향합니다.");
                    bus1.statuschange("차고지행");
                    System.out.println();
                    System.out.println("-----차고지-----");
                    int addgas1 = bus1.addgas(10);
                    System.out.println("주유량이 "+ addgas1+ "로 변했습니다.");

                    bus1.statuschange("운행중");
                    System.out.println();
                    System.out.println("다음 정류장에 도착했습니다.");
                    int pass2 = 45;

                    bus1.boarding(pass2);

                    System.out.println("정원초과여서 정류장을 지나칩니다.");
                    System.out.println();
                    System.out.println("다음 정류장에 도착했습니다.");

                    int pass3 = 5;
                    bus1.boarding(pass3);

                    int now2 = bus1.getPassengerNow();
                    System.out.println(now2);

                    System.out.println("잔여 승객 수는 "+ bus1.available(now2)+"명 입니다.");

                    int busfee2 = bus1.busfee(pass3);

                    System.out.println("버스 요금은 "+busfee2+"원 입니다.");

                    int minusgas = bus1.addgas(-55);
                    System.out.println("주유량이 " + minusgas + "로 변했습니다.");
                    bus1.isRunning();
                    System.out.println(bus1.getStatus());









                    }
                }


            break;

            }


        }


    }

혼공자 자바 java

메소드 선언부 method signiture

  • 리턴 타입: 메소드가 리턴하는 결과의 타입 푷시
  • 메소드 이름: 메소드의 기능이 드러나도록 식별자 규칙에 맞게 이름을 지어준다
  • 매개 변수 선언: 메소드를 실행할 때 데이터를 받기 위한 변수를 선언
  • 메소드 실행 블록: 실행할 코드를 작성

 

메소드 선언

  • 메소드 선언은 선언부와 실행 블록으로 구성

 

리턴 타입

  • 리턴값의 타입 == 실행한 후의 결과값
  • 메소드는 리턴값이 있을 수도 있고 없을 수도 있으나 리턴값이 있을 경우 리턴 타입이 선언부에 명시되어야 함

 

메소드 이름

  • 숫자로 시작하면 안되고 $와_를 제외한 특수문자 사용 금지
  • 관례적으로 메소드 이름은 소문자로 작성
  • 서로 다른 단어가 혼합된 이름이라면 뒤이어 오는 단어의 첫 글자는 대문자로 작성

 

매개 변수 선언

  • 메소드가 실행할 때 필요한 데이터를 외부로부터 받기 위해 사용

 

매개 변수의 개수를 모를 경우

  • 매개 변수를 배열 타입으로 선언하는 것
int sum1(int[] values){ }
int sum2(int ...values) { }

 

리턴문

  • 리턴값이 있는 메소드
  • return 리턴값;
  • return문이 없다면 컴파일 에러가 발생
  • return문이 실행되면 메소드는 즉시 종료

 

리턴값이 없는 메소드:void

  • void로 선언된 메소드에서 return은 메소드 실행을 강제 종료 시키는 역할을 함

 

메소드 호출

  • 메소드는 클래스 내.왜부의 호출에 의해 실행됨
  • 클래스 내부의 다른 메소드에서 호출할 경우 단순한 메소드 이름으로 호출하면 되지만
  • 클래스 외부에서 호출할 경우, 클래스로부터 객체를 생성한 뒤 참조변수를 이요해서 메소드를 호출해야함
  • 객체가 존재해야 메소드도 존재하기 때문

 

객체 내부에서 호출

메소드(매개값, ...);
타입 변수 = 메소드(매개값, ...);

 

객체 외부에서 호출

  • 외부 클래스에서 메소드를 호출하려면 클래스로부터 객체를 생성해야함
  • 메소드는 객체에 소속된 멤버이므로 객체가 존재하지 않으면 메소드도 존재하지 않기 때문
클래스 참조변수 = new 클래스 (매개값,..);

 

  • 객체가 생성되었다면 참조 변수와 함께 도트(.) 연산자를 사용해서 메소드를 호출

참조변수.메소드(매개값, ...);
타입 변수 = 참조변수.메소드(매개값, ...);

 

메소드 오버로딩

  • 클래스 내에 같은 이름의 메소드를 여러개 선언하는 것
  • 매개 변수의 타입, 개수, 순서 중 하나가 달라야 함
  • 매개값을 다양하게 받아 처리 할 수 있음
  • 이름만 다르다고 해서 오버로딩이 아님

 

확인 문제

  • 리턴값이 없는 메소드는 리턴 타입을 void로 해야한다.
  • 리턴 타입이 있는 메소드는 리턴값을 지정하기 위해 반드시 return문이 있어야한다
  • 매개값의 개수를 모를 경우 ... 를 이용해서 매개 변수를 선언할 수 있다.
  • 같은 이름의 메소드를 여러 개 선언하는 것을 메소드 오버로딩이라고 한다.

 

메소드 오버로딩에 대한 설명으로 맞는 것에 O/X

  • 동일한 이름의 메소드를 여러개 선언 하는 것을 말한다. (o)
  • 반드시 리턴 타입이 달라야 한다. (x)
  • 매개 변수의 타입, 개수, 순서를 다르게 선언해야 한다.(o)
  • 매개 값을 타입 및 개수에 따라 호출될 메소드가 선택된다 (o)

 

MemberService

public class MemberService {
    boolean login(String id, String password) {
        if (id.equals("hong") && password.equals("12345")) {
            return true;
        } else {
            return false;
        }
    }

    void logout(String id){
        System.out.println("로그아웃 되었습니다.");
    }
}

 

 

혼공자

생성자 constructor

new 연산자로 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당

 

객체 초기화

  • 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 하는 것
  • new 연산자에 의해 생성자가 실행되면 힙 영역에 객체가 생성되고 객체의 번지 리턴
  • 리턴된 객체의 번지는 클래스 변수에 저장

 

기본 생성자 default constructor

[public] 클래스() {}
  • 클래스가 public class로 선언되면 기본 생성자에도 public이 붙지만 클래스가 public 없이 선언되면 기본 생성자에도 public 없음

 

생성자 선언

클래스( 매개변수선언, ....){  객체 초기화 코드}

 

  • 리턴 타입이 없고 클래스 이름과 동일
  • 블록 내부에 객체 초기화 코드가 작성됨
  • 필드에 초기값을 저장하거나 메소드를 호출하여 객체 사용전에 필요한 준비를 함
  • 매개 변수는 new 연산자로 생성자를 호출할 때 외부의 값을 생성자 블록 내부로 전달하는 역할을 함

 

 

필드 초기화

  • 클래스로부터 객체가 생성될 때 필드는 기본 초기값으로 자동 설정됨
  • 초기화하는 방법
  • 필드를 선언할 때 초기값을 주는 방법
  • 생성자에게 초기값을 주는 방법

 

생성자 오버로딩

  • 매개변수를 달리하는 생성자를 여러개 선언하는 것

 

다른 생성자 호출: this()

  • 생성자에서 다른 생성차를 호출할 때 this()코드를 사용
  • 생성자의 첫 줄에서만 허용
  • this()의 매개값은 호출되는 생성자의 매개 변수에 맞게 제공해야 함
  • this() 다음에는 추가적인 실행문들이 올 수 있음
  • 호출되는 생성자의 실행이 끝나면 원래 생성자로 돌아와서 다음 실행문을 진행

 

확인 문제

  • 객체를 생성하려면 생성자 호출이 반드시 필요한 것은 아니다. (x)
  • 생성자는 다른 생성자를 호출하기 위해 this()를 사용할 수 있다. (o)
  • 생성자가 선언되지 않으면 컴파일러가 기본 생성자를 추가한다. (o)
  • 매개 변수의 수, 타입, 순서가 다른 생성자를 여러 개 선언할 수 있다. (o)

 

 

Member 클래스 작성

public class Member {
    
    String name;
    String id;
    
    public Member(String name, String id){
        this.name = name;
        this.id = id;
    }
}

 

Board 클래스 작성

public class Board {
    
    String title;
    String content;
    String writer;
    String date;
    int hitcount;
    
    Board(String title, String content, String writer, String date, int hitcount){
        this.title = title;
        this.content = content;
        this.writer = writer;
        this.date =date;
        this.hitcount = hitcount;
    }
    
    Board(String title, String content){
        this(title, content, "로그인한 회원아이디", "현재 컴퓨터 날짜", 0);
    }
    
    Board(String title, String content, String writer){
        this(title, content,writer,"현재 컴퓨터 날짜", 0);
    }
    
    Board(String title, String content, String writer, String date){
        this(title, content,writer,date,0);
    }
    
}

 

문제1. 윷놀이

우리나라 고유의 윷놀이는 네 개의 윷짝을 던져서 배(0)와 등(1)이 나오는 숫자를 세어 도, 개, 걸, 윷, 모를 결정합니다. 네 개 윷짝을 던져서 나온 각 윷짝의 배 혹은 등 정보가 주어질 때 도(배 1개, 등 3개), 개(배 2개, 등 2개), 걸(배 3개, 등 1개), 윷(배 4개), 모(등 4개) 중 어떤 것인지를 결정하는 프로그램을 작성하세요.

문제 풀이

[0,0,1,0] 0의 개수에 따라서 도,개,걸,윷,모 가 정해집니다.

0의 개수를 세서 각각의 경우의 수를 만들어주었습니다.

 

보자마자 쉽다는 생각이 드는 문제였습니다.

public class yutNori {
    public String solution(int[] arr1) {
       
        //0(배)의 개수에 따라서 정해진다. 도, 개 , 걸, 윷, 모

        String answer = "";
        int bae =0;

        for(int i=0; i<arr1.length; i++){
            if (arr1[i]==0){
                bae++;
            }

        if(bae==0){
             answer = "모";
        }
        if(bae==1){
            answer = "도";
        }
        if(bae==2){
            answer = "개";
        }

        if(bae==3){
            answer = "걸";
            }

        if(bae==4){
            answer = "윷";
            }

        }

        return answer;

    }

    public static void main(String[] args) {
    yutNori method = new yutNori();
    int[] s = {1,0,0,0};
        System.out.println(method.solution(s));




    }
}

 

문제2. Triangular Output aka. 피라미드 별찍기

피라미드 별찍기

위처럼 입력 값(int)에 따라 피라미드 모형을 별을 찍는 것을 구현합니다.

 

문제 풀이

1. 한 줄에 찍힌 별의 개수가 홀수 인 것을 알 수 있습니다.

2. 2*i+1 개씩 한 줄에 찍힙니다. 

3. for문을 이용해서 앞에 빈칸과 *을 찍어줍니다.

 

public class TriangularOutput {

        public void solution(int star) {
            //star는 피라미드의 층수
            //for문을 사용해서 *입력
            //2의배수에 +1 값이 한층당 *의 수
            //앞의 빈 칸만 만들어 주면 됨

            for (int i = 0; i <star ; i++) {

                for(int blank =1; blank<star-i; blank++) {
                    System.out.print(" "); //빈 칸 출력
                }

                for(int stars =0; stars<2*i+1; stars++){
                    System.out.print("*"); //* 출력; 별의 개수는 홀수
                }

                System.out.println(); //층 바꾸기
            }

        }

        public static void main(String[] args) {
            TriangularOutput method = new TriangularOutput();
            int star = 9;
            method.solution(star);
        }
    }

빈칸의 개수는 층수(i) -1 이고, 별의 개수는 층수(i) *2 +1 입니다.

 

반복문을 돌리면 피라미드가 완성됩니다.

 

 

문제3. 상하좌우 큰 수 찾기

5x5 2차원 배열이 주어질 때 어떤 원소가 상하좌우에 있는 원소보다 클 때 해당 위치에 * 을 표시하는 프로그램을 작성하세요. 경계선에 있는 수는 상하좌우 중 존재하는 원소만을 비교합니다.

 

문제 풀이

i'll get back to this

문제설명

양의 정수 x가 하샤드 수이려면 x의 자릿수의 합으로 x가 나누어져야 합니다. 예를 들어 18의 자릿수 합은 1+8=9이고, 18은 9로 나누어 떨어지므로 18은 하샤드 수입니다. 자연수 x를 입력받아 x가 하샤드 수인지 아닌지 검사하는 함수, solution을 완성해주세요.

제한 사항

x는 1 이상, 10000 이하인 정수입니다.

 

문제 풀이

1. int x 값을 String 타입으로 바꾼후 .split()을 이용해서 배열로 만든다.

2. 각 인덱스 값을 더해준다. -> int sum 

3. x를 sum으로 나눈 나머지가 ==0 이면 true, 아니면 false 를 리턴한다.

public class harshadNumber {
    public boolean solution(int x) {
        boolean answer = true;

        String num = String.valueOf(x);
        String[] numbers = num.split("");

        int sum =0;

        for (String number : numbers) {
            sum += Integer.parseInt(number);
        }
        
        if(x%sum==0){
            return answer;
        } else{
            answer=false;
            return answer;
        }

    }

    public static void main(String[] args) {
        harshadNumber method = new harshadNumber();
        System.out.println(method.solution(18));
    }
}

처음에 기본 for문을 사용했다가 향상된 for문을 사용해봤습니다.

훨씬 편하네요. 

자바로 입력된 배열의 최소값과 최대값 구하기에 대해 알아보겠습니다.

for문과 향상된 for문을 사용해서 최소값 최대값을 구합니다.

 

 

변수 선언

int[] arr = {12,14,16,18,23,5,68}; //배열 예시

int min = Integer.MAX_VALUE; //int 타입 범위에서 가장 큰 수
int max = 0; //둘 중에 더 큰 수를 저장할겁니다..

min 값을 설정할 때 int타입 범위에서 가장 큰 수로 저장하면 굳이 배열에 대한 범위를 신경쓰지 않아도 됩니다.

둘중에 작은 수를 저장하게 됩니다.

 

Integer.MAX_VALUE    // int 타입의 최대값
Integer.MIN_VALUE     // int 타입의 최소값

 

자바로 최대값 최소값 구하기 for문

배열값과 min, max 값을 비교해서 최소값, 최대값을 구합니다.

intellij에서 fori 단축키를 사용하면 for문이 자동으로 입력됩니다.

//for문 사용
for (int i = 0; i < arr.length ; i++) {

    if (arr[i]<min)
        min = arr[i];

    if (arr[i]>max)
        max = arr[i];
}
System.out.println("for문 사용>> max:"+max+" min:"+min);

 

자바로 최대값 최소값 구하기 향상된 for문

향상된 for문을 사용해서 최대값과 최소값을 구한다.

intellij에서 iter 단축키를 사용하면 향상된 for문이 자동으로 입력됩니다.

//향상된 for문 사용
for (int i : arr) {

    if(i<min)
        min = i;

    if(i>max)
        max = i;
}
System.out.println("향상된 for문 사용>> max:"+max+ " min:"+min);

 

 

자바 최대값 최소값 구하기 전체 코드

public class maxMin {
    public static void main(String[] args) {

        int[] arr = {12,14,16,18,23,5,68}; //배열 예시

        int min = Integer.MAX_VALUE; //int 타입 범위에서 가장 큰 수
        int max = 0; //둘 중에 더 큰 수를 저장할겁니다..


        //for문 사용
        for (int i = 0; i < arr.length ; i++) {

            if (arr[i]<min)
                min = arr[i];

            if (arr[i]>max)
                max = arr[i];
        }
        System.out.println("for문 사용>> max:"+max+" min:"+min);


        //향상된 for문 사용
        for (int i : arr) {

            if(i<min)
                min = i;

            if(i>max)
                max = i;
        }
        System.out.println("향상된 for문 사용>> max:"+max+ " min:"+min);
    }
}

 

프로그래머스 오버플로우 콜라츠 추측

문제 설명

1937년 Collatz란 사람에 의해 제기된 이 추측은, 주어진 수가 1이 될 때까지 다음 작업을 반복하면, 모든 수를 1로 만들 수 있다는 추측입니다. 작업은 다음과 같습니다.
1-1. 입력된 수가 짝수라면 2로 나눕니다. 
1-2. 입력된 수가 홀수라면 3을 곱하고 1을 더합니다. 
2. 결과로 나온 수에 같은 작업을 1이 될 때까지 반복합니다. 
예를 들어, 주어진 수가 6이라면 6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1 이 되어 총 8번 만에 1이 됩니다. 위 작업을 몇 번이나 반복해야 하는지 반환하는 함수, solution을 완성해 주세요. 단, 주어진 수가 1인 경우에는 0을, 작업을 500번 반복할 때까지 1이 되지 않는다면 –1을 반환해 주세요.

 

제한 사항

입력된 수, num은 1 이상 8,000,000 미만인 정수입니다.

 

문제 풀이

❗😱매개변수 num의 자료형을 int->long으로 변환하지 않으면 테스트3의 결과가 -1이 아닌 488로 다르게 나온다. 
😱😱😱😱연산 과정에서 오버플로우가 발생하기 때문이다. 따라서, public int solution(long num) 으로 바꿔야한다.

 

public class Collatz {

    public int solution(long num) {
            int answer = 0;

            if(num==1){
                answer =0;
            }

            while(num!=1){

                if(num%2==0){
                    num/=2;
                } else{
                    num = (num * 3) + 1;
                }

                answer++;

                if(answer>500){
                    return -1;
                }

            }

          return answer;

        }


    public static void main(String[] args) {
        Collatz method = new Collatz();
        System.out.println(method.solution(626331));
    }
}

 

오버플로우

선언 된 데이터 유형 범위를 벗어난 값을 할당 할 때 발생

연산과정에서 int 타입의 범위(-2^31 ( -2,147,483,648 )에서 2^31 -1( 2,147,483,647))를 벗어나면 계산이 안되고 멈춘다. 

num = 626311 에 대한 answer 값이 488 계속 나오길래 뭐가 잘못된 건가 Collatz의 추측이 맞았나 했는데

 

연산 값을 찍어보면, 104번째가 음수 -1085063658 으로 출력되었다. 

 

오버플로우로 값이 초과되서 음수로 표현이 되는 것이다.

 

103번째 num의 값은 홀수 이므로 1069967879*3+1 이 104번째 num값이 되어야하는데 int의 범위를 초과하는 것이다.

 

그래서 int타입을 long으로 변환해야 된다.

 

제일 작은 수 제거하기

 

문제 설명

정수를 저장한 배열, arr 에서 가장 작은 수를 제거한 배열을 리턴하는 함수, solution을 완성해주세요. 단, 리턴하려는 배열이 빈 배열인 경우엔 배열에 -1을 채워 리턴하세요. 예를들어 arr이 [4,3,2,1]인 경우는 [4,3,2]를 리턴 하고, [10]면 [-1]을 리턴 합니다.

 

제한 사항

  • arr은 길이 1 이상인 배열입니다.
  • 인덱스 i, j에 대해 i ≠ j이면 arr[i] ≠ arr[j] 입니다.

 

문제 풀이

1. 최솟값 int min 을 구한다.  for문을 돌린다. 

2. min과 같지 않은 수들로만 이루어진 배열을 새로 만든다. int[] num = new int[arr.length-1];

import java.util.Arrays;

import static java.util.Arrays.fill;

public class elimination {
    public int[] solution(int[] arr) {
        if(arr.length<=1){
        int[] answer = {-1};
        return answer;
        }

        int min = arr[0];

        for(int i=arr.length-1; i>0; i--){
            if(arr[i]<min){
                min = arr[i];
            }
        }
        System.out.println(min);

        int[] answer = new int[arr.length-1];
        int index=0;
        for(int i=0; i<arr.length;i++){
            if(arr[i]!=min){
            answer[index++]=arr[i];
        }

        }

        return answer;
    }

    public static void main(String[] args) {
        elimination method = new elimination();
        System.out.println(Arrays.toString(method.solution(new int[]{5,6,7,8})));
    }
}

 

오늘 오전에 언어 스터디를 했는데 조원분이 너무 멋진 객체지향 예제(보러가보세요!)를 보여주셔서 자극을 받아 바로 만들어 봅니다. 저는 식당 메뉴 별로 가격을 정하고 판매량 입력 후 매출 정산하는 프로그램을 만들어 보려고 합니다.

 

객체지향 예제

필드 선언

public class restaurantRevenue {
    //필드 선언
    private int price;
    private int revenue;
    private String menu;

    private int sold;

    //기본 생성자

    restaurantRevenue () {}



    //매개변수를 가진 생성자
    public restaurantRevenue(String menu, int price, int sold, int revenue) {
        this.menu = menu;
        this.price = price;
        this.sold = sold;
        this.revenue = revenue;
    }

    // getter setter 단축키 cmmd + N
    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public int getRevenue() {
        return revenue;
    }

    public void setRevenue(int revenue) {
        this.revenue = revenue;
    }

    public int getSold() {
        return sold;
    }

    public void setSold(int sold) {
        this.sold = sold;
    }

    public String getMenu() {
        return menu;
    }

    public void setMenu(String menu) {
        this.menu = menu;
    }
}

 

 

메뉴 입력 프로그램 만들기

import java.util.Scanner;

public class revenueExample {
    private Scanner scanner = new Scanner(System.in);

    private restaurantRevenue newMenu = null; //새 메뉴가 저장될 객체

    public revenueExample (){}; //기본 생성자

    public void display() { //메뉴화면 메소드

        int option = 0;

        do {
            System.out.println("=====*메뉴입력하기*=====");
            System.out.println("1. 메뉴입력");
            System.out.println("2. 판매량입력");
            System.out.println("3. 매출보기");
            System.out.println("0. 종료하기");
            System.out.print("선택>>");



            option = scanner.nextInt();

            switch (option) {
                case 1:
                    System.out.println(entermenu());
                    break;
                case 2:
                    System.out.println(sold());
                    break;
                case 3:
                    System.out.println(revenue());
                    break;
                case 0:
                    System.out.println("프로그램 종료!");
                    break;
                default:
                    System.out.println("다시 입력해주세요 -_-^");
            }


        }


        while (option != 0);
    }
    public String entermenu(){ //메뉴입력하기
        System.out.println("=====메뉴입력=====");
        System.out.print("메뉴명> ");
        String menu = scanner.next();
        System.out.print("가격> ");
        int price = scanner.nextInt();

        newMenu = new restaurantRevenue(menu, price,0,0);

        return "메뉴명:"+menu+" 가격: "+price+"원";
    }

    public String sold(){
        System.out.println("=====판매량입력=====");
        System.out.print("메뉴명> ");
        String menu = scanner.next();
        System.out.print("판매량> ");
        int sold = scanner.nextInt();

        if(menu.equals((newMenu.getMenu()))){
            newMenu = new restaurantRevenue(menu, newMenu.getPrice(), sold, sold* newMenu.getPrice());
            return "메뉴명: "+ menu + " 판매량: "+sold;
        }else {
            return "메뉴정보가 없습니다.";
        }


    }

    public String revenue(){
        System.out.println("=====매출보기=====");
        System.out.print("메뉴명> ");
        String menu = scanner.next();

        if(menu.equals((newMenu.getMenu()))) {
            return "메뉴명 " + menu + " 매출: " + newMenu.getRevenue();
        } else{
            return "메뉴정보가 없습니다.";
        }

    }

    public static void main(String[] args) {
        revenueExample revenue = new revenueExample();
        revenue.display();
    }

}


 

 

결과

=====*메뉴입력하기*=====
1. 메뉴입력
2. 판매량입력
3. 매출보기
0. 종료하기
선택>>1
=====메뉴입력=====
메뉴명> pasta
가격> 25000
메뉴명:pasta 가격: 25000원
=====*메뉴입력하기*=====
1. 메뉴입력
2. 판매량입력
3. 매출보기
0. 종료하기
선택>>2
=====판매량입력=====
메뉴명> pasta
판매량> 12
메뉴명: pasta 판매량: 12
=====*메뉴입력하기*=====
1. 메뉴입력
2. 판매량입력
3. 매출보기
0. 종료하기
선택>>3
=====매출보기=====
메뉴명> pasta
메뉴명 pasta 매출: 300000
=====*메뉴입력하기*=====
1. 메뉴입력
2. 판매량입력
3. 매출보기
0. 종료하기
선택>>2
=====판매량입력=====
메뉴명> rice
판매량> 40
메뉴정보가 없습니다.
=====*메뉴입력하기*=====
1. 메뉴입력
2. 판매량입력
3. 매출보기
0. 종료하기
선택>>3
=====매출보기=====
메뉴명> risotto
메뉴정보가 없습니다.
=====*메뉴입력하기*=====
1. 메뉴입력
2. 판매량입력
3. 매출보기
0. 종료하기
선택>>0
프로그램 종료!

Process finished with exit code 0

 

매우 간단하지만 굿 실습이었습니다.

혼자 공부하는 자바

 

필드

객체의 고유 데이터, 객체가 가져야 할 부품, 객체의 현재 상태 데이터를 저장하는 곳

 

필드 선언

  • {} 블록에 존재
  • 위치는 상관 없음
  • 단, 생성자와 메소드 중괄호 {} 내부에는 선언 될 수 없음
  • 생성자와 메소드 중괄호 블록 내부에 선언된 것은 모두 로컬 변수
  • 타입 필드 [=초깃값];
  • 선언형태는 변수와 피슷하지만 필드는 변수가 아님
  • 초기값이 저장되지 않은 필드는 객체 생성 시 자동으로 기본 초기값으로 설정됨
  • 참조 타입은 객체를 참조하고 있지 않은 상태인 null로 초기화

 

필드 사용

  • 필드값을 읽고 변경하는 작업
  • 클래스 내부의 생성자나 메소드에서 사용할 경우 필드 이름으로 일고 변경하면 됨
  • 클래스 외부에서 사용할 경우 우선적으로 클래스로부터 객체를 생성한 뒤 필드를 사용
  • 필드가 객체에 소속된 데이터이므로 객체가 있어야 필드도 존재함
  • 변수가 객체를 참조하게 되면 도트(.) 연산자를 사용해서 필드에 접근
  • 도트(.)연산자는 객체 접근 연산자

 

확인 문제

  • 필드는 메소드에서 사용할 수 있다. (o)
  • 필드는 클래스 블록 어디서든 선언할 수 있다(생성자, 메소드 내부 제외) (o)
  • 필드는 객체 외부에서 접근할 수 없다. (x)
  • 필드는 초기값을 주지 않더라도 기본값으로 자동 초기화 된다. (o)

 

Member Class 선언하기

public class Member {

    String name;
    String id;
    String password;
    int age;

    public static void main(String[] args) {
        Member member = new Member();
        member.name = "최하얀";
        member.age =23;

        System.out.println("이름: "+member.name);
        System.out.println("나이: "+member.age);
    }
}

필드 선언 연습

 

 

정수 제곱근 판별

 

문제 설명

임의의 양의 정수 n에 대해, n이 어떤 양의 정수 x의 제곱인지 아닌지 판단하려 합니다.n이 양의 정수 x의 제곱이라면 x+1의 제곱을 리턴하고, n이 양의 정수 x의 제곱이 아니라면 -1을 리턴하는 함수를 완성하세요.

 

제한 사항

n은 1이상, 50000000000000 이하인 양의 정수입니다.

 

문제 풀이

if else문을 사용하면 될 것 같습니다...?

 

1.  x*x == n 이면 (x+1)*(x+1) 을 리턴하고 else -1을 리턴한다.

2. sqrt(n) = x 

 

public class Squareroot {
    public long solution(long n) {
        long answer = 0;
        long x = 0;
        x = (long) Math.sqrt(n);
        if(x*x ==n){
            answer = (x+1)*(x+1);
        } else {
            answer = -1;
        }
        return answer;
    }

    public static void main(String[] args) {
        Squareroot method = new Squareroot();
        System.out.println(method.solution(121));
    }
}

 

 

+ Recent posts