package p03;
public class Cat {
// 인스턴스 변수 (필드)
String name;
int age;
String sex;
// 생성자
// 명시적으로 지정해주지 않으면, 기본 생성자가 자동으로 제공됨
// 명시적으로 만들면 기본 생성자는 자동생성 안됨
// public Cat() {} ;
// 명시적으로 여러 생성자 생성 ==> 오버로딩 생성자 (핸들링 클래스 내 호출 해 사용)
public Cat() {}
public Cat(int n) {}
public Cat(String n) {}
public Cat(String n, int a) {}
public Cat(String n, int a, String s) {
name = n;
age = a;
sex = s;
}
// Cat c = new Cat("야옹이", 2, "암컷"); <= Dog.java
// 야옹이가 n에 저장되고, n을 인스턴스 변수 name에 저장 (인스턴스 변수 초기화 수행)
}
package p03;
public class TestCat {
public static void main(String[] args) {
// 객체의 인스턴스 변수 초기화 방법 2가지
// 1. 생성자 사용
// 생성자 이용해서 초기화 하는 방법은 초기화 시점이 가장 빠른 방법이다.
//heap 메모리에 인스턴스 변수 할당 후(객체 생성)과 동시에 값이 초기화 됨
// 생성자 생성 후 핸들링 클래스의 main() { }내 호출하여 사용 필
Cat c = new Cat("야옹이", 2, "암컷");
// 인스턴스 변수에 직접 접근해서 초기화하는 방법은 초기화 시점이 매우 늦다
/* c.name = "야옹이"; // 객체 생성 이후에 name 변수에 값을 할당
c.age = 2;
c.sex = "암컷";
*/
}
}
return 용도:
메서드 호출 시 전달하는 인자값 종류
기본값
전달참조값(클래스, 배열)
전달 (주소값
전달) 객체 지향 프로그래밍의 4가지 특징
: 추상화, 상속, 다형성, 캡슐화
class Abc{
int a;
int b;
public Abc(a,b){
this.a = a;
this.b = b;
}
}
Abc abc = new Abc(1,2); //불가능
우리는 abc.a=error; abc.b=1;
과 같이 해당 변수에 직접 접근하여 그 값을 수정할 수 있다.
위 예제에서는 크게 문제가 되지않는다. 하지만 이런 접근은 위험하다.
개발자의 실수로 이어질 수도 있으며 안정성 또한 떨어진다.
class Abc{
private int a;
private int b;
public Abc(a,b){
this.a = a;
this.b = b;
}
}
package p02;
public class Cat {
// 필드
String name;
private int age; // 인스턴스 변수는 직접 접근하면 에러나서 접근 지정자로 private 설정해두는게 관례
String sex;
//생성자
public Cat() {
}
public Cat(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
//메서드
// setter 메서드 (인스턴스 변수에 값을 설정 ==> 값 변경도 설정에 해당)
// getter 메서드 (인스턴스 변수에 값을 조회)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
// 검증작업
public boolean ageCheck(int age) {
boolean result = true;
if(age > 0 && age < 20) {
result = false;
}
return result;
}
public void setAge(int age) {
// 검증 작업
if(ageCheck(age))
{
this.age = age;
}else {
System.out.println("입력 age 값을 다시 확인하세요");
}
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
// 추가 기능에 해당되는 메서드 지정
}
package p02;
import java06.Cat;
public class TestCat {
public static void main(String[] args) {
// 야옹이 2 암컷, 나비 1 숫컷
Cat c1 = new Cat("야옹이",2, "암컷");
//나이 수정
//c1.age = 300; // 논리적으로 문제가 됨.
c1.setAge(300);
//인스턴스 변수에 접근하려면 클래스 내부에서 getter와 setter 메소드를 사용해야 합니다.
//System.out.printf("이름:%s 나이:%d 성별:%s", c1.name, c1.age, c1.sex);
}
}
1) 목적: 클래스 파일 관리
2) 문법
Window 메뉴에서 Show View -> Navigator를 선택
3) 유일한 값 지정
4) package가 다르면 기존 방식으로 접근이 안된다.
public class TestMain {
public static void main(String[] args) {
com.daou.Cat c = new com.daou.Cat(); // 내가 접근하고자 하는 Cat이 어디에 있는지 알려주면 에러가 발생하지 않음
com.daou.Cat c2 = new com.daou.Cat(); // 내가 접근하고자 하는 Cat이 어디에 있는지 알려주면 에러가 발생하지 않음
}
}
java.
java.lang
은 import하지 않아도 사용 가능 import 패키지명.클래스명;
import 패키지명.*;
package com.example;
public class A {
//...
}
package com.example;
public class A { // 에러: 이전에 선언된 클래스와 이름이 중복됩니다.
//...
}
package com.example;
import otherpackage.A;
public class B {
A a = new A(); // 패키지 otherpackage에 있는 A 클래스를 사용합니다.
//...
}
package com.app1;
public class A {
public String name = "com.app1.A";
}
package com.app2;
public class A {
public String name = "com.app2.A";
}
package com.app1;
// 두 패키지 모두 명시적으로 지정하거나
// 둘 중 하나의 클래스를 import 패키지명.클래스명;
import com.app1.A;
public class TestA {
public static void main(String[] args) {
A a = new A();
System.out.println(a.name);
com.app2.A a2 = new com.app2.A();
System.out.println(a2.name);
}
}
+) Java API(Java Application Programming Interface)는 Java 표준 라이브러리를 말하며, Java 언어로 개발된 애플리케이션을 작성할 때 필요한 클래스, 인터페이스, 메소드, 상수 등의 집합을 제공합니다.
Java API는 패키지로 제공되며, 각 패키지에는 특정한 기능을 수행하는 클래스와 인터페이스가 포함되어 있습니다.
Java API는 JDK(Java Development Kit)에 포함되어 있으며, JDK를 설치하면 자동으로 사용할 수 있습니다.
import 패키지명.클래스명;
import 패키지명.*;
ctrl + shift + o
클래스명 + ctrl + space
import com.daou.Cat;
//import를 사용해 패키지 경로 지정하는 방법
// import com.daou.Cat;
public class TestMain2 {
public static void main(String[] args) {
/*com.daou.Cat c = new com.daou.Cat(); // 내가 접근하고자 하는 Cat이 어디에 있는지 알려주면 에러가 발생하지 않음
com.daou.Cat c2 = new com.daou.Cat(); // 내가 접근하고자 하는 Cat이 어디에 있는지 알려주면 에러가 발생하지 않음
*/
Cat c = new Cat();
Cat c2 = new Cat();
}
}
(cf. 제한 강도: private > default > protected > public)
4개의 접근 지정자는 클래스, 변수, 메서드, 생성자에 사용 가능
public
protected
default (package private)
상속 불가
private
부모클래스(parent class)로부터 상속받은 자식클래스(children class)는 부모클래스의 모든 자원과 메서드 등을 자신의 것 처럼 사용 할 수 있습니다.
하위클래스로 상속이 안되는 2가지 접근 지정자 : default, private
package com.app1;
public class Super {
public int n1 = 10;
protected int n2 = 20;
int n3 = 30;
private int n4 = 40;
}
package com.app2;
import com.app1.Super;
public class Sub extends Super{
private int m = 10;
public void info()
{
System.out.println(n1);
System.out.println(n2);
// System.out.println(n3);
// System.out.println(n4); private으로 인스턴스 변수 지정되어있음
System.out.println(m);
}
}
1) 사용:
2) 특징:
프로그램 실행할 때 메모리에 올라간다
=> 대표적인 메서드는 main 메서드이다.
method area에 저장된다.
단 한 번 생성된다
객체 생성 (new)과 관련 없다.
static 메서드에서 new 키워드를 사용할 수 없는 이유
static 메서드에서 this 키워드를 사용할 수 없는 이유
this는 인스턴스를 가리키는 참조 변수
따라서 인스턴스를 생성하지 않는 static 메서드 내부에서는 this 키워드를 사용할 수 없습니다.
따라서 static 메서드에서는 this를 사용하여 인스턴스의 메서드나 변수에 접근할 수 없습니다.
package p01;
public class Cat {
int n; // 인스턴스 변수, new (객체 생성)시 heap 메모리에 생성, new 할 때마다 매번 생성
static int n2; // static 변수(클래스 변수), 프로그램 실행 시 method area에 생성, 단 한번 생성
// 인스턴스 메서드, new(객체 생성)할 때 heap 메모리에 생성
public void a() {
System.out.println("a 메서드");
}
// static 메서드, 프로그램 실행 시 생성
// 주의할 점은 인스턴스 변수, this 사용 불가 ==> 이유는 아직 생성 안됨
public static void b() {
//System.out.println(n);//n은 인스턴스 변수이므로, 객체 생성 후 heap에 메모리 할당 하고나서 사용가능하다
System.out.println(n2);//n2은 static 변수이므로, 바로 사용가능하다
System.out.println("b 메서드");
// System.out.println(this); //인스턴스를 생성하지 않는 static 메서드 내부에서는 this 키워드를 사용할 수 없다.
}
}
// JVM 메모리 할당 시점이 static 이 먼저임 (static area)에 먼저 할당 되고, 인스턴스 변수가 new 키워드로 객체 생성 하여 heap 내 할당되는 건 이후 단계
// 즉, 인스턴스 변수는 시점이 static 메서드가 static area에 할당된 이후이므로,
// static 메서드는 아직 할당되지 않은 인스턴스 변수 및 인스턴스를 가리키는 참조값인 this에 접근할 수 없음
package p01;
public class TestMain {
public static void main(String[] args) {
// static 메서드는 객체 생성 없이 바로 호출 가능
// static 메서드는 여러 인스턴스에서 공유 가능
// static 메서드는 인스턴스에 속하지 않고 클래스에 속하며,
// 클래스의 모든 인스턴스에서 공유될 수 있습니다.
// 이는 static 메서드가 객체 생성과 무관하게 클래스의 로딩 시점에 이미 메모리에 적재되기 때문입니다.
System.out.println(Cat.n2);
Cat.b();
// 인스턴스 메서드는 반드시 new 키워드로 객체 생성 후 호출 가능
Cat c = new Cat();
System.out.println(c.n);
c.a();
// 인스턴스 메서드는 반드시 new 키워드로 객체 생성 후 호출 가능
Cat c2 = new Cat();
System.out.println(c.n);
c2.a();
}
}
JVM에서 클래스 로딩 시에는 static 블록이 먼저 실행되며, static 멤버 변수들은 이 때 클래스 영역(static area)에 메모리가 할당됩니다. 그리고 인스턴스 변수들은 객체 생성 시에 heap 영역에 메모리가 할당됩니다.
따라서, static 메서드에서는 객체가 생성되지 않은 시점에서 호출될 수 있기 때문에 인스턴스 변수나 this 참조를 사용할 수 없습니다.
이에 반해 인스턴스 메서드는 객체가 생성되고 나서 호출되기 때문에, 인스턴스 변수나 this 참조를 사용할 수 있습니다.
JVM 클래스 로딩 과정
이러한 순서로 메모리가 할당되며, 할당된 메모리는 사용이 끝나면 Garbage Collector에 의해 자동으로 해제됩니다. (더 이상 메모리 주소를 참조할 수 없음)
+) 메모리 구조
package p04;
import static java.lang.Math.PI;
public class TestMain {
public static void main(String[] args) {
// 1. "10" ---> 10
int num = Integer.parseInt("10");
System.out.println(num+1);
// 2. "10.3" --> 10.3
float f = Float.parseFloat("10.3");
System.out.println(f);
// 3. pi값
double pi = Math.PI;
System.out.println(PI);
}
}
package p04;
// 가독성 문제로 일반 java SE 환경에서는 잘 사용 안됨. 안드로이드에서 주로 사용 됨.
import static java.lang.Float.parseFloat;
import static java.lang.Integer.parseInt;
import static java.lang.Math.PI;
public class TestMain2 {
public static void main(String[] args) {
// 1. "10" ---> 10
int num = Integer.parseInt("10");
System.out.println(num+1);
// 2. "10.3" --> 10.3
float f = Float.parseFloat("10.3");
System.out.println(f);
// 3. pi값
double pi = Math.PI;
System.out.println(PI);
}
}