ArithmeticCalculator(has-a Value & ArithmeticOperator)
ArithmeticOperator – PLUS, MINUS, TIMES, DIVIDE, MODULATE
Value – int x, int y
ArithmeticCalculator
UserInput
ArithmeticCalculatorTest
Just another Kyoung Shin Park’s Lectures Sites site
ArithmeticCalculator(has-a Value & ArithmeticOperator)
ArithmeticOperator – PLUS, MINUS, TIMES, DIVIDE, MODULATE
Value – int x, int y
ArithmeticCalculator
UserInput
ArithmeticCalculatorTest
PhoneNumber – String workPhone, homePhone, cellPhone
Person – String name, PhoneNumber phone, String email
PersonContactTest (Person has-a PhoneNumber)
Person Struct (in C) PersonStructC
Person Class (in C++) PersonClassCPlusPlus
Person Class (in C#) PersonClassCSharp
Person Class (in Java) PersonClassJava
공용 데이터를 저장하여 사용하고자 할 때, singleton design pattern이나 inner static class를 사용한다.
싱글톤 패턴 (Singleton design pattern) -싱글톤 패턴이란 single instance object(해당 클래스의 인스턴스 하나)가 만들어지고, 어디서든지 그 싱글톤에 접근할 수 있도록 하기 위한 패턴
public final class SiteStructureSingletonPattern {
private Object[] data = new Object[10];
private static SiteStructureSingletonPattern instance = new SiteStructureSingletonPattern(); // private static member인 instance
public static SiteStructureSingletonPattern getInstance() { // getInstance() 메소드를 사용하여 instance 객체 사용
return instance;
}
private SiteStructureSingletonPattern() {
System.out.println("SiteStructureSingletonPattern constructor");
for(int i=0; i<10; i++) {
data[i] = i+1;
}
}
public void print() {
System.out.print("SiteStructureSingletonPattern data=");
for(int i=0; i<10; i++) {
System.out.print(" " + data[i]);
}
System.out.println();
}
}
public class SiteStructureStaticClass {
private Object[] data = new Object[10];
private static class SiteStructureStatic { // inner static class
private static final SiteStructureStaticClass instance = new SiteStructureStaticClass();
}
public static SiteStructureStaticClass getInstance() {
return SiteStructureStatic.instance;
}
private SiteStructureStaticClass() {
System.out.println("SiteStructureStaticClass constructor");
for(int i=0; i<10; i++) {
data[i] = i+1;
}
}
public void print() {
System.out.print("SiteStructureStaticClass data=");
for(int i=0; i<10; i++) {
System.out.print(" " + data[i]);
}
System.out.println();
}
}
public class StaticClassSingletonPatternTest {
public static void main(String[] args) {
SiteStructureSingletonPattern instance = SiteStructureSingletonPattern.getInstance();
instance.print();
instance = SiteStructureSingletonPattern.getInstance();
instance.print();
SiteStructureStaticClass instance2 = SiteStructureStaticClass.getInstance();
instance2.print();
instance2 = SiteStructureStaticClass.getInstance();
instance2.print();
}
}
// private constructor는 정적 메소드와 필드 (static method & field)만 있는 경우 사용함.
class Counter {
private Counter() { }
public static int currentCount;
public static int IncrementCount() { return ++currentCount; }
}
class TestCounter {
public static void main(String[] args) {
// If you uncomment the following statement, it will generate
// an error because the constructor is inaccessible:
//Counter aCounter = new Counter(); // Error
Counter.currentCount = 100;
Counter.IncrementCount();
System.out.println("count=" + Counter.currentCount); // count=101
}
}
// protected constructor는 추상클래스 (abstract class)에서 사용을 권고함. 추상 클래스를 상속받는 파생클래스에서 파생 클래스 생성자가 부모 클래스 즉, 추상 클래스를 초기화 하기 위해 추상 클래스 생성자를 호출 할 수 있도록 지원함.
public abstract class Shape {
protected Shape(String name) {
this.name = name;
}
private String name;
public void print() { System.out.print(this.name); }
}
public class Rectangle extends Shape {
private double width, height;
public Rectangle(String name) {
super(name);
this.width = 2;
this.height = 3;
}
@Override
public void print() {
super.print();
System.out.printf(" 가로: %f 세로: %f\n", this.width, this.height);
}
}
public class Triangle extends Shape {
private double bottom, height;
public Triangle(String name) {
super(name);
this.bottom = 1;
this.height = 1;
}
@Override
public void print() {
super.print();
System.out.printf(" 밑변: %f 높이: %f\n", this.bottom, this.height);
}
}
class ShapeTest {
public static void main(String[] args) {
//Shape s1 = new Shape("도형"); // Error; Shape is abstract; cannot be instantiated
Shape s = new Triangle("삼각형");
s.print(); // 삼각형 밑변: 1 높이: 1
s = new Rectangle("직사각형");
s.print(); // 직사각형 가로: 2 세로: 3
}
}
BankAccount-InstanceStatic – instance vs static member field & method
BankAccount-InstanceStatic
import java.util.*;
public class BankAccount {
private int balance;
private static int interestRate; // (%)
public BankAccount() {
balance = 0;
interestRate = 5;
}
public void deposit(int amount) {
balance += amount;
}
public void withdrawl(int amount) {
balance -= amount;
}
public void print() {
System.out.println("final balance=" +
(balance + balance * interestRate * 0.01) +
" balance=" +
balance +
" interest=" +
(balance * interestRate * 0.01));
printInterestRate();
}
public static void setInterestRate(int interestRate) {
BankAccount.interestRate = interestRate;
}
public static void printInterestRate() {
System.out.println("interestRate=" +
interestRate);
}
public int getUserInputInt() {
Scanner input = new Scanner(System.in);
System.out.print("Please enter Integer value: ");
int value = input.nextInt();
return value;
}
public static void main(String[] args) {
BankAccount b = new BankAccount();
b.deposit(2000);
b.withdrawl(1000);
b.print();
BankAccount.printInterestRate();
int amount = b.getUserInputInt();
b.deposit(amount);
b.print();
}
}
Instance member field: int value
Static member field: static int count
public class ValueClass {
private int value = 0; // instance field
private static int count = 0; // static field
static Scanner input = new Scanner(System.in); // static field
public ValueClass() {
this(0);
}
public ValueClass(int value) {
this.value = value;
count++;
}
public void setValue(int value) { // instance method
this.value = value;
}
public int getValue() { // instance method
return this.value;
}
public void print() { // instance method
System.out.println("value=" + this.value + " # of value=" + count);
}
public static int getCount() { // static method
return count;
}
public static void printString(String str) { // static method
System.out.print(str);
}
public static int getUserInputInt() { // static method
int value = input.nextInt();
return value;
}
public static void main(String[] args) {
ValueClass v = new ValueClass();
v.print();
v.setValue(2000);
int value = v.getValue();
v.print();
ValueClass.printString("Please enter the integer value: ");
int val = ValueClass.getUserInputInt();
v.setValue(val);
v.print();
ValueClass v2 = new ValueClass(300);
v2.print();
ValueClass[] vArray = new ValueClass[3];
for (int i=0; i<3; i++) {
ValueClass v3 = new ValueClass();
ValueClass.printString("Please enter the integer value: ");
v3.setValue(ValueClass.getUserInputInt());
vArray[i] = v3;
}
}
}
PersonTest-InstanceStatic – instance member field & method vs static member field & method
public class Person {
String name; // instance member field
int age; // instance member field
public Person() { // default constructor
this("JAVA17", 2017); // call Person(String n, int a);
}
public Person(String name, int age) { // constructor
this.name = name;
this.age = age;
}
public void setName(String name) { // instance method
this.name = name;
}
public void setAge(int age) { // instance method
this.age = age;
}
public String getName() { // instance method
return name;
}
public int getAge() { // instance method
return age;
}
public void print() { // instance method
System.out.println("Person Name=" + name + " Age=" + age);
}
@Override
public String toString() { // instance method
return "Person Name=" + name + " Age=" + age;
}
}
public class Person2 {
static String name; // static member field
static int age; // static member field
public Person2() { // default constructor
this("JAVA17", 2017); // call Person2(String n, int a);
}
public Person2(String n, int a) { // constructor
name = n;
age = a;
}
public static void setName(String n) { // static method
name = n;
}
public static void setAge(int a) { // static method
age = a;
}
public static String getName() { // static method
return name;
}
public static int getAge() { // static method
return age;
}
public static void print() { // static method에서는 this 사용 불가
System.out.println("Person Name=" + name + " Age=" + age);
}
@Override
public String toString() {
return "Person Name=" + name + " Age=" + age; // instance method에서는 static member variable 접근 가능
}
}
public class Person3 {
static String name; // static member field
static int age; // static member field
private Person3() { // private default constructor
}
public static void setName(String n) { // static method
name = n;
}
public static void setAge(int a) { // static method
age = a;
}
public static String getName() { // static method
return name;
}
public static int getAge() { // static method
return age;
}
public static void print() { // static method에서는 this 사용 불가
System.out.println("Person Name=" + name + " Age=" + age);
}
}
public class PersonTest {
static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
Person[] pArray = new Person[3];
// 만약 Person 객체를 하나만 생성한 후 for문에서 공유해 사용할 경우
// 마지막으로 입력된 데이터로 모든 데이터값이 치환됨
Person p = new Person();
for (int i = 0; i < 3; i++) {
System.out.print("\n\nEnter Person name and age : ");
p.setName(input.next()); // 입력정보
p.setAge(input.nextInt()); // 입력정보
p.Print();
pArray[i] = p; //배열에 들어간 모든 원소는 동일한 p
}
System.out.println("pArray : " + Arrays.toString(pArray));
Person[] pArray1 = new Person[3];
// 아래와 같이 for문 안에 Person p = new Person()와같이
// 새로운 객체를 생성해야 각자 다르게 입력된 정보가 들어가게 됨
for (int i = 0; i < 3; i++) {
Person p1 = new Person();
System.out.print("\n\nEnter Person name and age : ");
p1.setName(input.next()); // 입력정보
p1.setAge(input.nextInt()); // 입력정보
p1.Print();
pArray1[i] = p1; // p1는 새로운 Person객체이므로 배열에서 각각 다른 원소가 들어간다
}
System.out.println("pArray1 : " + Arrays.toString(pArray1));
// 만약 Person2 객체의 name과 age는 static이라서,
// static은 공유하는 것이므로, 마지막으로 입력된 데이터로 모든 데이터값이 치환됨
Person2[] pArray2 = new Person2[3];
for (int i = 0; i < 3; i++) {
Person2 p2 = new Person2();
System.out.print("\n\nEnter Person name and age : ");
p2.setName(input.next()); // Person2.setName(input.next())와 동일
p2.setAge(input.nextInt()); // Person2.setAge(input.nextInt())와 동일
pArray2[i] = p2; // p2 객체의 name과 age는 static이므로 모두 공유하기때문에, 배열의 모든 원소는 마지막에 들어간 정보로 셋팅
}
System.out.println("pArray2 : " + Arrays.toString(pArray2));
Person3[] pArray3 = new Person3[3]; // Person3 타입의 배열생성 OK
for (int i = 0; i < 3; i++) {
//Person3 p3 = new Person3(); // error Person3() has private access
System.out.print("\n\nEnter Person name and age : ");
Person3.setName(input.next()); // p3.setName(input.next()) 사용을 못하게 함
Person3.setAge(input.nextInt()); // p3.setAge(input.nextInt()) 사용을 못하게 함
//pArray3[i] = p3; // error p3 객체를 생성할 수 없으므로 사용 불가능
}
Person3.print();
default (package private – access in other classes within the same package)
public (visible everywhere)
protected (only access in its own class, its subclass and other classes within the same package)
private (only access in its own class)
http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
Modifier | Class | Package | Subclass | World |
---|---|---|---|---|
public |
Y | Y | Y | Y |
protected |
Y | Y | Y | N |
no modifier | Y | Y | N | N |
private |
Y | N | N | N |
https://www.baeldung.com/java-permgen-metaspace
Permgen (JDK7 이전)
Metaspace (JDK8 이후)
클래스의 정보가 로드되는 영역, 정적 멤버 (static member) 저장, 바이트코드나 JIT 정보 저장