
A는 B의 외부 클래스, B는 A의 내부 클래스
class A{
int i=100;
B b = new B();//객체 생성
}
class B{
void method(){
A a = new A();//객체 생성
System.out.println(a.i);
}
}
class C{
B b = new B();//객체 생성
}
public class InnerTest {
public static void main(String[] args) {
B b= new B();//객체 생성
b.method();
}
}
위와 같이 어느 클래스에서 다른 클래스로 접근하려면, 반드시 객체를 생성해야만 했다.
class A{ //A는 B의 외부 클래스
int i=100;
B b = new B();
class B{ // B는 A의 외부 클래스, B는 A 안에서만 사용 가능(캡슐화)
void method(){
/*A a = new A();
System.out.println(a.i);*/
System.out.println(i); //객체 생성없이 외부 클래스 멤버 접근
}
}
/*class C{
B b = new B();
}*/
public class InnerTest {
public static void main(String[] args) {
/* B b= new B();
b.method();*/
}
}
A 클래스는 B 클래스를 멤버처럼 사용 가능하다.
class Outer{
private class InstanceInner{}
protected static class StaticInner{}
void myMethod(){
class localInner{}
}
}
내부 클래스의 경우 private,protected,default,public 모두 사용 가능하다.
class Ex{
class InstanceInner{
int iv = 100;
static int cv = 100; //static 변수를 선언할 수 없다.
final static int CONST = 100; //final static은 상수이므로 선언 가능
}
static class StaticInner{
int iv = 200;
static int cv = 200; //static 클래스만 static 멤버를 정의할 수 있다.
}
void myMethod(){
class localInner{
int iv = 300;
static int cv = 300; //static 변수를 선언할 수 없다.
final static int CONST = 300; //final static은 상수이므로 선언 가능
int i = LocalInner.CONST; // 이건 가능
}
public static void main(String[] args) {
System.out.println(InstanceInner.CONST);
System.out.println(StaticInner.cv);
//System.out.println(LocalInner.CONST);
//지역 내부 클래스의 static 상수는 메서드 내에서만 사용 가능하다.
}
}

package study.first;
public class Study {
public static void main(String[] args) {
Outer p = new Outer(); // Outer 클래스 인스턴스 생성
Outer.Inner c = p.new Inner(); // Outer.Inner 클래스 인스턴스 생성
System.out.println(c.a);
c.print();
}
}
class Outer {
class Inner {
int a = 1;
void print() {
System.out.println(a + " 함수");
}
}
}
class PocketBall {
// 인스턴스 변수
int size = 100;
int price = 5000;
// 인스턴스 내부 클래스
class PocketMonster {
String name = "이상해씨";
int level = 10;
// static int cost = 100; - 에러! 인스턴스 내부 클래스에는 static 변수를 선언할 수 없다.
static final int cost = 100; // final static은 상수이므로 허용
public void getPoketMember() {
// 별다른 조치없이 외부 클래스 맴버 접근 가능
System.out.println(size);
System.out.println(price);
// 내부 클래스 멤버
System.out.println(name);
System.out.println(level);
System.out.println(cost);
}
}
}
public class Main {
public static void main(String[] args) {
PocketBall ball = new PocketBall(); // 먼저 외부 클래스를 인스턴스화 해주고
PocketBall.PocketMonster poketmon = ball.new PocketMonster(); // 외부클래스.내부클래스 형식으로 내부클래스를 초기화 하여 사용할 수도 있다
poketmon.getPoketMember();
// 위의 단계를 한줄로 표현
PocketBall.PocketMonster poketmon2 = new PocketBall().new PocketMonster();
}
}
// 외부 클래스
public class Main {
public print(String txt) {
System.out.println(txt);
}
// 내부 클래스
class Sub {
public print() {
}
}
}
public class Main {
public void print(String txt) {
System.out.println(txt);
}
class Sub {
public void print() {
Main.this.print("외부 클래스 메소드 호출");
System.out.println("내부 클래스 메소드 호출");
}
}
}
public static void main(String[] args) {
Main.Sub s = new Main().new Sub();
s.print();
/*
외부 클래스 메소드 호출
내부 클래스 메소드 호출
*/
}
package study.first;
public class Study {
public static void main(String[] args) {
Outer.Inner c = new Outer.Inner();
System.out.println(c.a);
c.print();
}
}
class Outer {
static class Inner {
int a = 1;
void print() {
System.out.println(a + " 함수");
}
}
}
class PocketBall {
int size = 100;
static int price = 5000;
// static 내부 클래스
static class PocketMonster {
static String name = "이상해씨";
int level = 10;
public static void getPoketMember() {
// 외부 클래스 인스턴스 맴버 접근 불가능
// System.out.println(size);
// 외부 클래스 스태틱 멤버 접근 가능
System.out.println(price);
// 내부 클래스 멤버도 스태틱 맴버만 접근 가능
System.out.println(name);
// System.out.println(level);
}
}
}
public class Main {
public static void main(String[] args) {
// 스태틱 내부 클래스의 인스턴스는 외부 클래스를 먼저 생성하지 않아도 된다.
PocketBall.PocketMonster poketmon = new PocketBall.PocketMonster();
System.out.println(poketmon.level);
System.out.println(PocketBall.PocketMonster.name);
// 클래스.정적내부클래스.정적메소드()
PocketBall.PocketMonster.getPoketMember();
}
}
package study.first;
public class Study {
public static void main(String[] args) {
Outer p = new Outer();
p.print();
}
}
class Outer {
void print() {
class Inner {
int a = 1;
}
Inner c = new Inner();
System.out.println(c.a);
}
}
class PocketBall {
int size = 100;
int price = 5000;
public void pocketMethod() {
int exp = 5000;
// 메소드 내에서 클래스를 선언
class PocketMonster {
String name = "이상해씨";
int level = 10;
public void getPoketLevel() {
System.out.println(level); // 인스턴스 변수 출력
System.out.println(exp); // 메소드 지역 상수 출력
}
}
// 메소드 내에서 클래스를 선언
class PocketMonster2 {
String name = "리자몽";
int level = 50;
}
new PocketMonster().getPoketLevel();
System.out.println("메소드 실행 완료");
}
}
class Creature {
int life;
public void method() {
Animal animal = new Animal(); // Animal 객체는 오로지 Creature 클래스의 메소드 내에서만 사용된다고 가정
// ...
}
}
// 외부에 선언된 클래스
class Animal {
}
class Creature {
int life;
// 클래스 멤버 같이 Creature 클래스 안에다 넣어 선언한다.
class Animal {
}
public void method() {
Animal animal = new Animal(); // Animal 객체는 오로지 Creature 클래스의 메소드 내에서만 사용된다고 가정
// ...
}
}
이렇게 클래스 안에 넣어주게 되면, 클래스간의 상관관계를 빠르게 파악할 수 있다.(가독성 UP)
class Creature {
private int life = 50;
// private class 로, 오로지 Creature 외부 클래스에서만 접근 가능한 내부 클래스로 설정
private class Animal {
private String name = "호랑이";
int getOuter() {
return life; // 외부 클래스의 private 멤버를 제약 없이 접근 가능
}
}
public void method() {
Animal animal = new Animal();
// Getter 없이 내부 클래스의 private 멤버에 접근이 가능
System.out.println(animal.name); // 호랑이
// 내부 클래스에서 외부 클래스이 private 멤버를 출력
System.out.println(animal.getOuter()); // 50
}
}
이렇게 내부 클래스를 사용하는 궁극적인 목적은 해당 클래스안에서만 사용할거면, 굳이 다른 곳에서 선언하지 말고, 안에서 선언하기 위함이다.