Java - Class, import, package, 메서드, Scope, static

김지원·2022년 7월 19일
0

JAVA 총 정리

목록 보기
1/11

Class

Class의 명명법

  • 명명법(Naming Convention) : 파스칼 케이스 (Pascal Case), 첫자 대문자, 단어간 구분 대문자, 나머지 소문자
    참고) 변수의 명명법은 카멜케이스이다.

Class의 목적

: 서로 관련있는 멤버(Member)의 집합이다.

Class 작성법(Syntax)

[접근 제한자 (Access Modifier)] [(abstract | final)?] class [이름] [extends [class]?] [implements [InterFace], ...? {...}
  • ?는 써도되고 안써도되는 것을 의미한다.

접근 제한자 (Access Modifier)

  • public : 제한 없음
  • protected : 같은 패키지(Package)에 있거나, 상속관계에 있을 경우에만 접근
  • (default) : 같은 패키지에 있을 경우에만 접근 (아무것도 적지 않으면 default임)
  • private : 현재 객체 내에서만 접근

  • default 이다.

클래스의 접근 제한자는 public과 (default)만 가능하다. (그렇지만 반듯이 그런것은 아님을 알고 있어야한다.)

❗️ 접근 제한자가 public 인 클래스의 이름은 파일의 이름과 같아야한다.

  • public일꺼면 파일이름과 똑같이 만들어야한다는 오류를 띄워준다.
    Class 'ClassBasicTemp' is public, should be declared in a file named 'ClassBasicTemp.java'

같은 패키지 내에 동일한 이름을 가지는 클래스를 여러개 만들 수 없는데, 이는 한 파일 내에 접근 제한자가 public인 클래스가 2개 이상일 수 없음을 의미하기도 한다.

  • 접근제한자가 public이 아니고 클래스명이 다르면 오류가 뜨지 않는다.

한 파일에 여러개의 클래스를 쓸 일을 크게 없다.


Package

Package의 명명법

명명법 : 스네이크 케이스(Snake Case), 전체 소문자, 단어간 구분은 언더스코어(_). 가령, some_package_name

Package의 목적

  1. 프로젝트 소유자 구분 + 구성요소의 충돌 방지 (도메인의 역순부터 시작)
  2. 클래스 등의 구성요소의 종류별 | 기능별 구분

-> 1번에 대해서..

항상 소유자 구분을 위해서 항상 도메인의 역순을 적어줘야한다.
이 세상에는 많은 사람들이 개발에 유용한 자바 프로젝트를 배포해주는데 흔하게 사용될 수 있는 이름이 겹치면 안된다.

예를 들어보자.

  • CharacterEnocder이라는 클래스에 들어가서 보았을 때 패키지 경로가 sun.misc 로 설정이 되어있다.
    sun 사가 있고 또 다른 sun2사가 둘 다 CharacterEnocder 만들었다고 가정을 해보자. CharacterEnocder을 사용을 할 때 package에 경로를 명시를 해주지 않았다면
    누구의 CharacterEnocder를 사용하는지 모르게 된다.
    misc안에는 CharacterEnocder가 두개가 존재하게 되버리는데 public 안에는 같은 이름 두개를 사용할 수 없다.
    그래서 도메인을 역순을 적어주어서 겹침을 막는다.

패키지를 만들어보자.

  • dev.jwkim로 패키지를 만들었을 때 이렇게 표시가 된다.
  • Open in -> Finder 로 확인해보니 우리가 알고 있는 그냥 폴더로 존재한다. 어렵게 생각하지 말자.

  • dev.jwkim 패키지 안에 Alpha라는 클래스를 만들었더니 위에 package dev.jwkim; 이렇게 패키지의 경로가 적히게 되는걸 볼 수 있다.

  • dev.jwkim 패키지 밖에 같은 이름의 Alpha클래스를 생성해도 아무런 문제가 발생하지 않는다. 왜냐하면 위에서 설명한 CharacterEnocder의 예시처럼 패키지의 경로를 설정해주었기 때문에 다른 클래스라는 것을 명시를 해준거나 마찬가지임으로 오류가 발생하지 않는 것이다.

  • 다시 돌아와서 CalssBasic의 메인메서드에서 Alpha를 적어보았더니 두 개의 클래스가 뜨는 것을 볼 수 있고 두 개의 경로가 다른 것도 확인이 가능하다.

  • 아래의 dev.jwkimAlpha를 탭을 해보았다.

  • 자동으로 import dev.jwkim.Alpha; import가 되는 것을 확인 할 수 있다.
  • import가 있으면 Alpha를 Command + Click 시 패키지 경로가 있는 클래스(dev.jwkim.Alpha) 로 연결이 된다.
  • import 주석처리시 패키지 경로가 없는 Alhpa(Alhpa)로 가게 된다.

import 목적

패키지 경로가 다른 클래스 및 구성요소를 사용하겠다는 의미이다. 단, 사용처의 패키지 경로와 같은 구성요소를 사용할 때에는 import가 필요하지 않다.
만약 import 없이 어떠한 구성요소를 사용코자 한다면 풀 네임을 작성한다. 자동완성을 이용하였을 때에만 import가 자동으로 추가된다.

  • import없이 패키지가 있는 Alpha로 가기 위해서는 dev.jwkim.Alpha alpha2; 이렇게 풀네임을 작성해주면 된다.
  • 작성한 Alpha 두 개는 타입이 완전 다른 것이다.

접근제한자에 대해서 예제를 통해 알아보자.

  • 패키지 없는 Alpha에서 public으로 sayHello라는 메서드를 만들었다.

  • 메인에서 Alpha 를 적으니 바로 아래에 sayHello 라는 메서드가 뜨는 것을 볼 수 있다. 즉 public으로 만든 메서드는 다른 클래스에서 호출이 가능하다는 것이다.
  • 실행 시 잘 나온다.

같은 패키지에 있기 때문에 public을 protected로 바꾸어도 실행이 된다. 물론 default도 가능하다.

=> private도 해보자.

  • 패키지 없는 Alpha에서 sayHello메서드의 publicprivate로 변경하였다.
  • 그런다음 ClassBasic 클래스에서 호출을 해보았더니 오류가 발생한다.
    private는 해당 클래스안에서만 사용이 가능하기 때문에 호출을 못하는 것이다. 'sayHello()' has private access in 'Alpha' : Alpha 안에서만 사용할 수 있다.

알뜰신잡) Delegation : 대리자

  • 패키지 없는 Alpha에서 sayHelloDelegation()메서드를 만들어보았고 sayHelloDelegation()안에서 sayHello() 메서드가 호출이 가능한 것을 볼 수 있다.
    같은 클래스 안에 있기때문에 오류가 뜨지 않는다.

  • ClassBasic 클래스에서 private인 sayHello()를 호출하고 있는sayHelloDelegation()를 호출을 했는데 오류가 발생하지 않는다.

  • 이런 방향으로 흘려가기 때문에 오류가 발생하지 않음.

메서드 Method

: 지정된 (최소한의) 동작을 하기 위해 존재하는 호출(Call) 가능한 실행 단위이다.

Method 명명법

: 카멜 케이스

Method 작성법

[접근 제한자] [static | final | abstract ?] [반환 타입 | void] [이름] ( [매개 변수 선언, ...] ? ) { ... } 
  • 메서드가 가지는 접근 제한자와 클래스가 가진 접근 제한자는 똑같이 작동한다. (같은 것이다.)

메서드는 우리가 알고 있는 함수와 비슷하며 기능상으로 똑같다고 생각하면 된다.

f(a, b) = a + b
f(5, 3) = 8

-> sum이라는 메서드를 생성하였고 메인메서드에서 sumResult를 출력하면 8이 찍히게 하자.

  • int sumResult = sum(3, 5);
    여기서 사용한 sum은 메서드를 호출한다 라고 표현한다.
  • ❕ sum 메서드를 호출하며 3과 5를 전달인자(Argument)로 전달하였다.

-> 전달인자로써 값을 받기 위해서 매개변수로 써줘야한다.(8분)

  • 3과 5는 각각 a와 b에 들어가게 된다.
  • 보통 실무에서는 둘다 매개변수로 부르는 일이 많다..!

❗️ sum(3, 5); : 전달인자(Argument)
❗️ sum(int a , int b) : 매개변수(Parameter)

  • 매개변수도 (정의되어있는 변수 == ) 메서드안에서 사용될 수 있는 변수인 만큼 중복 될 수 없다!

-> 매개변수를 지정해주었으니 출력을 해보자.

  • 매개변수도 지정하였는데 오류가 발생한다.
    호출한 결과가 int여야하는데 void네? 라는 의미의 오류이다.
    Required type : int
    Provided : void

void

: 반환 값이 없는 메서드

  • 정확히는 타입은 아니다.

  • 아래의 메서드에 반환 타입을 int로 수정해주었더니 오류가 사라졌다.
    메서드를 호출하면 int 타입의 값을 반환한다!
    그런데 타입에 대한 오류는 사라졌지만 아래에서 오류가 터졌다.

  • Missing return statement : 리턴이 없다라는 오류가 뜬다.

❗️반환 타입이 void가 아닌 모든 메서드는 대부분의 경우에 return 키워드를 이용하여 값을 반환해야한다.

대부분의 경우라고 한 이유는 만약 if문을 사용했을 때 리턴을 하지 않을 경우가 있다. if문의 조건에 부합해야 리턴을 하기 때문이다. (if문안의 return을 의미함)


-> sum메서드를 호출했을 때 결과가 두 변수의 합일 것이다. => a + b
앞에 return을 붙여주면 된다!

-> return 후 sout을 해보려니..

  • Unreachable statement : 도달할수없는 구문이다 라는 오류가 뜬다.
    return이 발생하면 그 자리에서 메서드 실행을 중단한다.
    메서드 실행이 중단되면 main으로 돌아간다고 해도되지만 정확히는 sum이라는 메서드를 호출한 곳으로 돌아간다.

추가 )
스레딩을 하지 않으면 실행점은 1개이다. ( = 실제로 실행되는 메서드가 한개이다. )

int sumResult 은 sum(3, 5); 의 실행이 끝날때가지 기다린다.
실행이 끝나서 int sumResult = 8 이 되면 세미콜론을 만나서 sout으로 내려오게 된다.

둘 다 동시에 실행을 하게 되면 오류가 터진다. 값이 돌아오기 전에 실행점이 아래줄로 내려가버리면 sumResult 가 뭔지모르는 상황이기 되버리기 때문이다.
이런걸 멀티스레딩이라고 한다.

max 메서드

: 전달 받은 정수형 변수 a와 b중 더 큰 값을 반환하는 메서드


클래스가 가지는 모든 것들이 멤버다.

스코프(Scope)

: 메서드 내에서 변수 등에 접근할 수 있는 범위에 대한 정의

  • 메인 메서드의 최상위 스코프는 구현부 ({ }) 이다.

멤버변수(Member Variable)

: 클래스가 가지는 변수

멤버변수 특징

멤버변수에 값을 명시하지 않을 경우 기본값으로 초기화한다.

  • 숫자 : 0
  • 논리 : false
  • 문자 : '\u0000'**
    u는 뒤에 숫자 4자리에 대한 유니코드를 이용하곘다는 의미이다.
  • 참조타입 : null

지역변수 (Local Varible)

: 메서드가 가진 변수

지역변수 명명법

: 카멜 케이스

지역변수 특징

값이 초기화 되지 않은 지역 변수에는 값 대입을 제외한 접근을 할 수 없다.


Variable 'n' might not have been initialized 변수 n이 초기화가 되지않았을 수도 있다. 라는 오류가 뜬다.

실행점 기준 선언되지 않은 변수에 접근할 수 없다.

보다 하위 스코프에 선언된 변수에 접근할 수 없다.

  • 보다 위에있지만 하위 스코프이기 때문에 사용할 수 없다.

지역변수는 정적일 수 없다.

전역변수값을 명시하지 않았을 때랑 지역변수값을 명시하지 않을 때 두개의 상황은 완전 다르다.



double pi = 3.14D; : 멤버 변수
int r = 5; : 지역 변수


static

: 정적인 것.

  • static을 붙으면 정적메서드 / 정적인 메서드 라고 부른다. ( 정적인 메인 메서드 )

정적이다 라는 것에 대한 특징!

예를 들어 배그게임을 실행하면 로비가 켜질때까지 오래걸린다. 정적인 코드가 너무 많아서 그렇다. 초반에 불러올 것이 많다면 (정적인 메서드가 많다면) 메모리를 엄청나게 사용하게 된다.

실행 → 준비 → 메인

우리는 메인부터 개발을 한다.
준비상태는 우리가 직접 작성한 정적인 코드들을 메모리(Ram)에 올리는 것이다.
→ static딱지가 붙은 애들을 main이 실행되기 전에 메모리에 올린다.

메인메서드가 실행될 때 정적인 것들을 모두 준비가 되어있는 상태일 것이다.
그렇다면 비정적인 것들을 어떻게 되는가?

  • 여기서 비정적인 친구는 pi 일 것이다.
    메인메서드가 실행되는 시점에는 double pi = 3.14D; 가 없기 때문에 pi를 출력하려고 하면 오류가 뜨게 된다. r은 메모리에서 알고 있기 때문에 정상적으로 작동이 된다.

더 상세하게 설명을 해보자면,
r 이라는 변수에 배정된 주소값은 변수에 주소가 따라다니기 때문에 이미 프로그램이 알고있다.

메인메서드는 실행을 누르자 마자 메모리에 올라가는데 pi는 메인메서드 안에 존재하지 않는다.
즉 메모리에 올라간 메인메서드에는 pi라는 것이 존재하지 않는다.

그렇다면 pi를 출력할 수 있는 방법은 없을까?

❗️ 메인메서드가 호출되기 전에 pi 라는 아이의 존재를 알려주면 해결이 될 것이다!
→ static을 붙이면 된다.

  • static이니깐 메인메서드가 실행되기 전에 메모리에 pi를 올릴 것이다.

  • 메서드 안에서는 정적인 것을 만들 수 없다. 접근할 방법이 없기 때문이다. (객체화를 해주면 되기는 한다....)

-> sum이라는 비정적 메서드를 만들고 메인메서드에서 호출을 해보았다.

  • 정적인 것 내부에서 비정적인 것을 접근하지마라 라는 오류가 발생한다. ( 객체화를 하기 전까지는 )
    Non-static method 'sum(int, int)' cannot be referenced from a static context
    비정적인것은 정적인 것보다 한참 미래에 메모리에 올라갈 것이기 때문에 반대로는 (비정적인 것에서 정적인 것에 대한 접근) 가능하다.

객체화

멤버라는 클래스를 객체화하면 멤버클래스가 가진 비정적인 것들에 대해서 접근을 할 수 있다.

  • Member클래스를 Member member = ; 이렇게 적어주었고 Type은 Member이며 참조 타입이다.
    참고 ) 원시타입 8개를 제외한 모든것은 참조타입이다.

  • Member 클래스를 적고 . 을 찍어보니 main 메서드와 `pi가 보인다.
  • 알고보니 main과 pi의 공통점은 static 이다!

정적인 멤버는 클래스로 접근한다.
비정적인 멤버는 객체로 접근한다.

  • new Member(); 새로운 멤버다 라고 해주니 sum 접근이 가능하다.
    비정적인 멤버에 접근을 하려면 객체화를 해야된다.
    member 는 객체 혹은 변수라고 한다.
profile
Software Developer : -)

0개의 댓글