- 명명법(Naming Convention) : 파스칼 케이스 (Pascal Case), 첫자 대문자, 단어간 구분 대문자, 나머지 소문자
참고) 변수의 명명법은 카멜케이스이다.
: 서로 관련있는 멤버(Member)의 집합이다.
[접근 제한자 (Access Modifier)] [(abstract | final)?] class [이름] [extends [class]?] [implements [InterFace], ...? {...}
- ?는 써도되고 안써도되는 것을 의미한다.
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이 아니고 클래스명이 다르면 오류가 뜨지 않는다.
한 파일에 여러개의 클래스를 쓸 일을 크게 없다.
명명법 : 스네이크 케이스(Snake Case), 전체 소문자, 단어간 구분은 언더스코어(_). 가령,
some_package_name
- 프로젝트 소유자 구분 + 구성요소의 충돌 방지 (도메인의 역순부터 시작)
- 클래스 등의 구성요소의
종류별 | 기능별
구분
-> 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.jwkim
의Alpha
를 탭을 해보았다.
- 자동으로
import dev.jwkim.Alpha;
import가 되는 것을 확인 할 수 있다.- import가 있으면 Alpha를
Command + Click
시 패키지 경로가 있는 클래스(dev.jwkim.Alpha
) 로 연결이 된다.- import 주석처리시 패키지 경로가 없는 Alhpa(
Alhpa
)로 가게 된다.
패키지 경로가 다른 클래스 및 구성요소를 사용하겠다는 의미이다. 단, 사용처의 패키지 경로와 같은 구성요소를 사용할 때에는 import가 필요하지 않다.
만약 import 없이 어떠한 구성요소를 사용코자 한다면 풀 네임을 작성한다. 자동완성을 이용하였을 때에만 import가 자동으로 추가된다.
- import없이 패키지가 있는 Alpha로 가기 위해서는
dev.jwkim.Alpha alpha2;
이렇게 풀네임을 작성해주면 된다.- 작성한 Alpha 두 개는 타입이 완전 다른 것이다.
접근제한자에 대해서 예제를 통해 알아보자.
- 패키지 없는
Alpha
에서public
으로sayHello
라는 메서드를 만들었다.
- 메인에서
Alpha
를 적으니 바로 아래에sayHello
라는 메서드가 뜨는 것을 볼 수 있다. 즉public
으로 만든 메서드는 다른 클래스에서 호출이 가능하다는 것이다.
- 실행 시 잘 나온다.
같은 패키지에 있기 때문에 public을 protected로 바꾸어도 실행이 된다. 물론 default도 가능하다.
=> private도 해보자.
- 패키지 없는
Alpha
에서sayHello
메서드의public
을private
로 변경하였다.
- 그런다음
ClassBasic
클래스에서 호출을 해보았더니 오류가 발생한다.
private는 해당 클래스안에서만 사용이 가능하기 때문에 호출을 못하는 것이다.'sayHello()' has private access in 'Alpha'
: Alpha 안에서만 사용할 수 있다.
알뜰신잡) Delegation : 대리자
- 패키지 없는
Alpha
에서sayHelloDelegation()
메서드를 만들어보았고sayHelloDelegation()
안에서sayHello()
메서드가 호출이 가능한 것을 볼 수 있다.
같은 클래스 안에 있기때문에 오류가 뜨지 않는다.
ClassBasic
클래스에서 private인sayHello()
를 호출하고 있는sayHelloDelegation()
를 호출을 했는데 오류가 발생하지 않는다.
- 이런 방향으로 흘려가기 때문에 오류가 발생하지 않음.
: 지정된 (최소한의) 동작을 하기 위해 존재하는 호출(Call) 가능한 실행 단위이다.
: 카멜 케이스
[접근 제한자] [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
: 반환 값이 없는 메서드
- 정확히는 타입은 아니다.
- 아래의 메서드에
반환 타입을 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
가 뭔지모르는 상황이기 되버리기 때문이다.
이런걸 멀티스레딩이라고 한다.
: 전달 받은 정수형 변수 a와 b중 더 큰 값을 반환하는 메서드
클래스가 가지는 모든 것들이 멤버다.
: 메서드 내에서 변수 등에 접근할 수 있는 범위에 대한 정의
- 메인 메서드의 최상위 스코프는 구현부 (
{ }
) 이다.
: 클래스가 가지는 변수
멤버변수에 값을 명시하지 않을 경우 기본값으로 초기화한다.
- 숫자 :
0
- 논리 :
false
- 문자 :
'\u0000'
**
u는 뒤에 숫자 4자리에 대한 유니코드를 이용하곘다는 의미이다.- 참조타입 :
null
: 메서드가 가진 변수
: 카멜 케이스
값이 초기화 되지 않은 지역 변수에는 값 대입을 제외한 접근을 할 수 없다.
Variable 'n' might not have been initialized
변수 n이 초기화가 되지않았을 수도 있다. 라는 오류가 뜬다.
실행점 기준 선언되지 않은 변수에 접근할 수 없다.
보다 하위 스코프에 선언된 변수에 접근할 수 없다.
- 보다 위에있지만 하위 스코프이기 때문에 사용할 수 없다.
지역변수는 정적일 수 없다.
전역변수값을 명시하지 않았을 때랑 지역변수값을 명시하지 않을 때 두개의 상황은 완전 다르다.
double pi = 3.14D;
: 멤버 변수
int r = 5;
: 지역 변수
: 정적인 것.
- 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
는 객체 혹은 변수라고 한다.