Class 파스칼 (대문자로 시작)
메소드명 대문자로시작
메소드변수,변수 카멜케이스 (소-대)
데이터베이스 스네이크_표기법
클래스자료형 대문자로 시작
상수 대문자,스네이크로표기
메소드명,변수명을 만들 때는 어떤 행동을 하는지 명확해야하며 단일책임원칙을 따르는 게 좋다
변수선언
생성자
getter & setter
equals
hashcode
toString
public class ColorMain {
public static void main(String[] args) {
boolean isRun = true;
while(isRun){
isRun = false;
}
}
}
class Method{
void addUser(String name){
}
}
단일책임원칙 : 한개의 메소드는 하나만의 임무를 수행해야한다
구조체 = 객체(Object) = 클래스
클래스 = 양식
인쇄한 양식 = 객체
양식을 적어낸 결과물 = 인스턴스 (할당된 공간)
그냥 계속해서 사용할 것이기 때문에 클래스를 만드는 것이고 그 안에서 method를 만듬으로써 이용하는 것
사용하는 이유 : 함수를 이용할 때 배열에 있는 모든 데이터를 통째로 보낼 수 있으며, 필요한 것만 꺼내 쓸 수 있음
배열공간을 늘리거나 줄일 수 없지만 더 큰 공간을 생성해서 값을 대입한 뒤에 그공간 자체를 다시 대입하는 방법이 있다
arr = Arrays.copyOf(arr, arr.length + 1);
작은공간 = 큰공간 선언 하면 늘어남
배열 상위호환 List → ArrayList가 있음
for,forEach,while
배열과 함께 자주사용하며 말그대로 반복을 위해서 사용하는 것
for(int i = 0; i < n.length; i++) // n의 값이 i보다 크다는 조건식이 성립할 때 까지 반복
초기화식 조건식 증감식
for(int arr : arrays) // arr의 첫번째 인덱스부터 끝까지 반복
for문의 경우 인덱스에 값을 넣어주거나 순서 또는 규칙이 있을 때 사용함
forEach의 경우 처음부터 끝까지 반복하거나 값을 비교할 때 사용
while의 경우에는 정해진 값이 들어올 때까지 반복할 경우에 사용
오버로딩과 오버라이딩은 전혀 다른것임
Overloading : 메서드명은 같지만 매개변수의 유형과 갯수를 달리하여 같은 메서드명에 다양하게 들어오는 값들을 처리하기위해서 사용한다
Overriding(재정의) : 상속받은 메서드를 확장 또는 재구성해서 사용하는 것
(양식,틀 을 받아서 채워넣는 거)
누군가가 이미 만들어놓은 코드의 모음집이다
정해진 이름으로 호출함으로써 양식에 맞춰 편하게 사용할 수 있음
컬렉션 프레임워크 안에 라이브러리가 있다고 보면됨
( 컬렉션프레임워크 = 도구함 , 라이브러리 = 카테고리가 나뉘어진 도구들)
List , Set , Map , Stack , Queue, Tree ,Linked 등등 해당됨 전부 반복가능함
List,Set,Queue는 Collection을 상속받는다 (List,Set,Queue도 전부 인터페이스임)
List가 상위요소(인터페이스) ArrayList가 하위요소(상속 받아서 구현한 클래스)
그냥 배열 관련이면 ArrayList 사용 하면 된다
선언 할 땐 상위 자료형(List, Set, Map) 에서 하위 자료형(ArrayList, HashSet, HashMap)으로 생성
상위 자료형은 생성이 불가능하다 → 인터페이스이기 때문
범용성(확장성)을 생각해서 상위요소로 선언 해놓는 게 좋다
Map은 제네릭 타입이 다르기 때문에 별도이다.
컬렉션 프레임워크는 wrapper자료형을 선호하기 때문에 참조메서드를 사용할 시 자료형에 주의할 것
(Wrapper는 제네릭에서 다루겠다)
// 배열을 List로 만들어주는 것
List<String> list = Arrays.asList(배열);
// ArrayList로 형변환 다운캐스팅하기
ArrayList<String> list2 = (ArrayList<String>)Arrays.asList(strArray);
Set<Map.Entry<String, String>> entries = lang.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println("key : " + entry.getKey());
System.out.println("value : " + entry.getValue());
}
List,Set은 반복이 가능하지만 Map의 경우엔 반복이 불가(for 사용불가하다는 뜻)하므로 Set으로 만들어주고
Key,Value로 나누어져있던 값들을 .entrySet()
을 사용함으로써 묶어줌으로써 반복이 가능해짐
순서가 없는 객체에 순서(인덱스)를 지정해서 감싸는 것이라고만 알고있자
abstract와 interface
두가지 다 큰 틀을 잡는데 사용하면 유용하다
공통사항이 있는 것들을 한데 묶는 작업이며,
메서드를 수정, 추가 해서 쓰고싶다면
확장,재정의해서 사용하면 된다
abstract 추상클래스의 경우에는 extends
interface의 경우에는 implements ( 인터페이스간에는 extends )
public abstract class AbstractCar {}
public interface Button {}
>>> 이렇게 두가지가 있고 구현하고싶다면
// 해서 안에서 재정의 해주고 main클래스에서 생성 하여 사용
public class KiaCar extends AbstractCar
// 인터페이스도 마찬가지
public class ButtonImpl implements Button
추상의 경우에는 상속을 받아서 확장하는 용도라한다면 (선천적 유전자)
인터페이스는 기능만을 제시해놓고 구현(Overrindg)해서 사용하는 용도 (후천적기술)
추상클래스도 인터페이스도 자체생성이 불가하고 무조건 상속 또는 구현한 클래스를 생성해야한다
+익명클래스로는 사용가능
익명 클래스는 말 그대로 생성이 불가한 추상클래스, 인터페이스를 사용하고자 하는 클래스에서 바로 호출하여, 그자리에서 재정의해서 사용하는 것이다.
터치 또는 클릭이라는 기능에 나가기버튼 , 로그인 버튼, 홈으로가기 버튼 등등
약 80개 정도의 버튼에서 시작되는 기능들이라하면
일일히 구현,상속 받아서 클래스파일을 만들어줄 순 없다 그럴 때 사용하는 게 익명 클래스
사용하고자 하는 부분에서 바로 불러내서 그자리에서 재정의하는 것임
package com.study.java_study.ch19_익명클래스;
public class ButtonMain {
public static void main(String[] args) {
// 기존에 사용하던 방법
Button button = new HomeButton();
button.onClick();
// 익명클래스 생성하여 바로 재정의
Button loginButton = new Button() {
@Override
public void onClick() {
System.out.println("로그인 하기");
}
};
인터페이스던 추상클래스던 생성은 불가하므로 상속 또는 구현한 걸 생성하여 참조해서 사용했었음 그러나
익명클래스의 경우 추상클래스,인터페이스 자체를 불러옴으로써 바로 재정의하는 걸 볼 수 있다.
결론 : 생성은 안되는 거 맞고 클래스명도 없는건데 기능은 가져다 쓸 수 있다
해당클래스에 하나의 메서드만 있을 때 사용가능하며 , 코드를 간소화할 수 있다는 장점이 있다.
람다만을 사용하기 위한 인터페이스들이 있음 @FunctionalInterface 라고 명명
(오직하나의 메서드만 선언,사용가능)
람다인터페이스 기능들
// 단순 실행
Runnable runnable = () -> {}; / runnable.run
// 매개변수도 있고 반환도 해주는 기능적인 메서드
Function<T, R> fx = (t) -> {Return r}; fx.apply(T)
// 단순 소비 → 매개변수를 가져가서 이용만 함 , 반환은 없음
Consumer<T> consumer = (t) -> {}; / consumer.accept
// 매개변수는 없고 반환만 있음 Consumer와 반대
Supplier<R> role = () -> {return r}; / role.get()
// boolean 으로 반환해주는 메서드
Predicate<T> even = n -> n % 2 == 0; // even.test(n)
T : 매개변수 자료형
R : 반환 자료형
말 그대로 하나만 최초로 생성해서 모든곳에서 통용되게 사용하는 것
@Autowired / private final 클래스명
동적 메모리할당(생성) = new
정적(static) → 이미 공간이 할당 되어있어 생성할 필요없이 바로 사용가능
생성을 해야 사용할 수 있는 변수,메서드는 사용불가
= 메모리에 존재하지 않으면 사용할 수 없음
같은 클래스 안에 있어도 Static으로 설정하면
Static안에서 생성자를 만들거나 쓰고자하는 변수도 Static으로 만들어줘야한다
같은 주소의 데이터를 다른클래스에서 사용하려할 때 (공유할 때) 유용하다
생성자를 하나만(private) 생성하여 그것만을 계속 사용하겠다.
외부에서 생성이 불가능하게 막아야한다 (private static)
외부에서 접근이 가능한 static 메서드 하나 만들어둔다
같은 클래스에서 해당 메서드를 사용하고싶다면 생성을 해주어야한다.
public class StudentService {
private static StudentService instance;
private StudentService() {}
public static StudentService getInstance() {
if (instance == null) {
instance = new StudentService();
}
return instance;
}
의미 : 이미 주소를 할당받았다면 그 주소를 계속해서 사용하겠다.
public class StudentMain {
public static void main(String[] args) {
StudentService studentService = StudentService.getInstance(); // 같은
StudentService studentService2 = StudentService.getInstance(); // 주소
생성을 변수명으로 아무리 해봤자 같은 주소값을 사용한다.
데이터를 넣어서 사용하고자 할 때 받고자 하는 양식이 다를 수 있음
예) 이름, 나이 , 주소 , 성별
전체생성자의 경우 선언과 동시에 값을 넣어줘야하는 방법이 있고(이건 문제가 안됨)
기본생성자(NoargsConstructor)와 Setter를 이용해서, 값을 일일히 대입해주는 번거로운 방법이 있다
후자의 경우 좀 더 편한 방법이 없을까 해서 나온 패턴이 Builder 패턴이다.
내부클래스,static를 이용하여 해당 데이터에 접근을 하고 보내준다.
package com.study.java_study.ch18_빌더;
public class DataEntity {
// 기존 데이터들
private String data1;
private int data2;
private double data3;
private String data4;
// 전체생성자
public DataEntity(String data1, int data2, double data3, String data4) {
this.data1 = data1;
this.data2 = data2;
this.data3 = data3;
this.data4 = data4;
}
// builder로 불러올 거
public static DataEntityBuilder builder() {
return new DataEntityBuilder();
}
// 내부 클래스
public static class DataEntityBuilder {
private String data1;
private int data2;
private double data3;
private String data4;
// 생성자에 넣어줄 메서드들
public DataEntityBuilder data1(String data1) {
this.data1 = data1;
return this;
}
public DataEntityBuilder data2(int data2) {
this.data2 = data2;
return this;
}
public DataEntityBuilder data3(double data3) {
this.data3 = data3;
return this;
}
public DataEntityBuilder data4(String data4) {
this.data4 = data4;
return this;
}
// 자료형 맞춰서 값 보내주기
public DataEntity build() {
return new DataEntity(data1, data2, data3, data4);
}
}
}
static은 static으로만 접근 가능 굳이 사용하려한다면 해당클래스를 생성 후 그객체를 참조해서 사용해야함.
이런식으로 돌아간다는 것만 알고 우린 @builder
를 사용하면 된다
클래스 내부에 선언 된 또 다른 클래스를 의미
사용하는 이유 ?
하나의 클래스에서만 필요한 메서드들이나 변수가 존재한다면 내부에 클래스를 생성해서 사용함으로써 가독성이 좋아지고 유지관리가 쉬워짐
캡슐화 : private 제어자를 이용하여, 외부에서 접근을 차단하는 반면, 내부클래스에선 외부클래스의 멤버들을 제약없이 접근 가능하여 구조적이고 효과적인 프로그래밍이 가능하다.
변수의 타입을 일반화시키는 것 (wrapper 자료형 전부를 받겠다)
Object 의 경우에는 업캐스팅 되었다가 다시 다운캐스팅 해야하기 떄문에 번거로움
사용하고자 하는 클래스 를 명시 해줌으로써 사용가능
제네릭 타입은 무조건 Wrapper 자료형으로 사용된다 ( 일반 자료형 사용불가 )
와일드카드 <?> → Object의 기호
// [ Wrapper 자료형 ]
// Integer int
// Boolean -언박싱-> boolean
// Charcter <-박싱- char
// Double double
// Long long
// Float float
범위 지정
// 하행
// 해당 클래스 본인과 상속받은 것들만 사용가능
Message<? extends String> m3 = new Message<>("10");
// 상행
// 본인과 본인의 상위 클래스는 전부 사용 가능
Message<? super String> m4 = new Message<>(new Object());