Instance vs Static Method Overriding

PersonStudentClass

/// Person

class Person
{
static int count = 0; // static (class) variables

String name; // instance variables
int age; // instance variables

public Person()
{
//System.out.println(“Person Constructor”); // this(“”, 0); error: call to this must be first statement in constructor
this(“”, 0);
}

public Person(String name, int age)
{
count++;
this.name = name;
this.age = age;
}

public static void printCount() // static (class) method
{
System.out.println(“Person Count: ” + count);
}

public static int getCount() { return count; } // static (class) methods

 

public String toString() // Object.toString() overriding
{
return “Person Name: ” + name + ” Age: ” + age;
}

public void print() // instance methods
{
System.out.println(“Person Name: ” + name + ” Age: ” + age);
}
}

/// Student

class Student extends Person
{
static int scount = 0; // static (class) variables
int id;

public Student()
{
this(“”, 0, 5208);
}

public Student(String name, int age, int id)
{
super(name, age);
this.id = id;
scount++;
}

public static void printCount() // static (class) method overriding
{
System.out.println(“Student Count: ” + scount);
}

public String toString() // Object.toString() overriding
{
return “Student Name: ” + name + ” Age: ” + age + ” ID: ” + id;
}

public void print() // Person class print() method overriding
{
System.out.println(“Student Name: ” + name + ” Age: ” + age + ” ID: ” + id);
}

}

 

class PersonStudentTest
{
public static void main(String[] args)
{
Person p1 = new Student(“Kyoung”, 22, 1207);
p1.print(); // dynamic binding Student Name: Kyoung Age: 22 ID: 1207
p1.name = “JAVA”; // default (package private)
p1.age = 1; // default (package private)
//p1.id = 2016; // default (package private) cannnot call id coz Person System.out.println(p1); // dynamic binding Student Name: JAVA Age: 1 ID: 1207
p1.printCount(); // calls Person p1 printCount() 1
Person.printCount(); // calls Person printCount() 1
Student.printCount(); // calls Student printCount() 1
System.out.println();

Student s1 = (Student)p1;
s1.name = “JAVA”; // default (package private)
s1.age = 2; // default (package private)
s1.id = 2016; // default (package private)
s1.print(); // Student Name: JAVA Age: 2 ID: 2016
s1.printCount(); // calls Student s1 printCount() 1
Person.printCount(); // calls Person printCount() 1
Student.printCount(); // calls Student printCount() 1
System.out.println();

Student s2 = new Student(“Shin”, 20, 1207);
s2.print(); // Student Name: Shin Age: 20 ID: 1217
s2.printCount(); // calls Student s2 printCount() 2
Person.printCount(); // calls Person printCount() 2
Student.printCount(); // calls Student printCount() 2
System.out.println();

Person p2 = new Person(“Park”, 10);
p2.printCount(); // calls Person p2 printCount() 3
Person.printCount(); // calls Person printCount() 3
Student.printCount(); // calls Student printCount() 2
System.out.println();

Person p3 = new Person();
p3.printCount(); // calls Person p3 printCount() 4
Person.printCount(); // calls Person printCount() 4
Student.printCount(); // calls Student printCount() 2
System.out.println();

System.out.println(“Number of Person: ” + Person.getCount()); // 4
}
}

 

Method Overloading vs Overriding

http://www.programmerinterview.com/index.php/java-questions/method-overriding-vs-overloading/

Method Overloading: 동일한 함수명에 매개변수가 다른 함수를 둘 이상 정의하는 것으로, 동일한 함수 기능을 수행하지만 다른 매개변수의 경우를 처리할 때 사용
//compiler error – can’t overload based on the 
//type returned (one method returns int, the other returns a float):
//int changeDate(int Year) ;
//float changeDate (int Year);

//compiler error – can’t overload by changing just
//the name of the parameter (from Year to Month):
//int changeDate(int Year);
//int changeDate(int Month) ;

//valid case of overloading,
//since the methods have different number of parameters:
int changeDate(int Year, int Month) ;
int changeDate(int Year);

//also a valid case of overloading,
//since the parameters are of different types:
int changeDate(float Year) ;
int changeDate(int Year);

Method Overriding: 상속받은 파생 클래스에서 동일한 함수명에 동일한 매개변수로 정의하여 함수를 재정의하는 것으로 상속되어진 함수의 기능을 변경해서 재사용하고 싶을 때 사용

public class Parent {

public int someMethod() {

return 3;

}
}

public class Child extends Parent{

// this is method overriding:
public int someMethod() {

return 4;

}

}

Person Array

PersonTest-InstanceStatic

instance member field & method vs static member field & method 이해

public class Person {
String name; // instance member field
int age;
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) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void print() {
System.out.println(“Person Name=” + name + ” Age=” + age);
}
@Override
public String toString() {
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=” + this.name + ” Age=” + this.age; // instance method에서는 static member variable 접근 가능
}
}

 

public class Person3 {
static String name; // static member field
static int age; // static member field
private Person3() { // 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[] pArray2 = new Person[3];
// 아래와 같이 for문 안에 Person p = new Person()와같이
// 새로운 객체를 생성해야 각자 다르게 입력된 정보가 들어가게 됨
for (int i = 0; i < 3; i++) {

Person p2 = new Person();

System.out.print(“\n\nEnter Person name and age : “);
p2.setName(input.next()); // 입력정보
p2.setAge(input.nextInt()); // 입력정보
p2.Print();

pArray2[i] = p2; // p2는 새로운 Person객체이므로 배열에서 각각 다른 원소가 들어간다

}

System.out.println(“pArray2 : ” + Arrays.toString(pArray2));

 

Person2[] pArray3 = new Person2[3];
// 만약 Person2 객체의 name과 age는 static으로 사용할 경우
// static은 공유하는 것이므로, 마지막으로 입력된 데이터로 모든 데이터값이 치환됨
for (int i = 0; i < 3; i++) {

Person2 p3 = new Person2();

System.out.print(“\n\nEnter Person name and age : “);
p3.setName(input.next()); // Person2.setName(input.next())와 동일
p3.setAge(input.nextInt()); // Person2.setAge(input.nextInt())와 동일

pArray3[i] = p3; // p3 객체의 name과 age는 static이므로 모두 공유하기때문에, 배열의 모든 원소는 마지막에 들어간 정보로 셋팅

}

System.out.println(“pArray3 : ” + Arrays.toString(pArray3));

Person3[] pArray4 = new Person3[3]; // Person3 타입의 배열생성 OK
for (int i = 0; i < 3; i++) {

//Person3 p4 = new Person3(); // error Person3() has private access

System.out.print(“\n\nEnter Person name and age : “);
Person3.setName(input.next()); // p4.setName(input.next()) 사용을 못하게 함
Person3.setAge(input.nextInt()); // p4.setAge(input.nextInt()) 사용을 못하게 함

//pArray3[i] = p4; // error p4 객체를 생성할 수 없으므로 사용 불가능

}

Person3.print();

Lab3

Lab3 프로젝트 디렉토리 안에 모든 파일(src/*.java & bin/*.class)와 보고서 (2~3장)를 넣고 Lab3_학번_이름.zip 압축한 후 e-learning

(http://lms.dankook.ac.kr/index.jsp)으로 제출 ()

Lab3 – Class/OOP

수업블로그에 클래스 OOP 참고하여, 본인이 작성한 Lab2를 객체지향적인 프로그램으로 바꾼다. 그리고 본인이 원하는 Converter 클래스를 하나더 추가 작성한다 (예시: degree <-> radian 변환, kilometer <-> mile 변환, kilogram <-> pound 변환, 등등). ConverterMode 를 사용해줄 것!

http://www.unitconverters.net/
보고서는 출력해서 수업시작 전에 제출한다.

보고서의 내용은 기존 코드 분석과 이해한 내용 그리고 본인이 추가한 코드내용을 적는다..

 

public enum ConverterMode {
FAHRENHEIT_TO_CELSIUS(1),
CELSIUS_TO_FAHRENHEIT(2),
KILOMETER_TO_MILE(3),
MILE_TO_KILOMETER(4);

private final int type;
ConverterMode(int type) {
this.type = type;
}
public int getType() {
return type;
}
public static ConverterMode valueOf(int value) {
switch(value) {
case 1: return FAHRENHEIT_TO_CELSIUS;
case 2: return CELSIUS_TO_FAHRENHEIT;
case 3: return KILOMETER_TO_MILE;
case 4: return MILE_TO_KILOMETER;
}
return null;
}
}

 

// main

public static void main(String[] args) {
calculate(1);
calculate(2);
calculate(3);
calculate(4);

for (ConverterMode c: ConverterMode.values()) {
calculate(c);
}
}

singleton design pattern vs static class

공용 데이터를 저장하여 사용하고자 할 때, singleton design pattern이나 내부 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 SiteStructureSingletonPattern() {
System.out.println(“SiteStructureSingletonPattern constructor”);
for(int i=0; i<10; i++) {
data[i] = i+1;
}
}

public static SiteStructureSingletonPattern getInstance() {
return instance;
}

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 SiteStructureStaticClass() {
System.out.println(“SiteStructureStaticClass constructor”);
for(int i=0; i<10; i++) {
data[i] = i+1;
}
}

private static class SiteStructureStatic {
private static final SiteStructureStaticClass instance = new SiteStructureStaticClass();
}

public static SiteStructureStaticClass getInstance() {
return SiteStructureStatic.instance;
}

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();
}

}

 

Static vs Instance Initializer Block

Static Initializer Block

  • class 로딩 시 호출
  • instance variable이나 method에 접근 못함
  • static variable 초기화에 사용

public class StaticIntializerBlockTest {
private static int id = 5;
static {
if (id <10) id = 20;
else id = 100;
}

public static int getId() {
return id;
}

public static void print()
{
System.out.println(“StaticIntializerBlockTest.id=” + getId());
}
}

public class StaticInstanceInitializerBlockTest {

public static void main(String[] args) {
StaticIntializerBlockTest.print();
}

}

StaticIntializerBlockTest.id=20 // static block 이 호출되면서 20으로 셋팅

Instance Initializer Block

  • 객체 생성시 호출
  • super 생성자 이후에 실행하고, 생성자보다 먼저 실행
  • instance variable이나 method에 접근 가능
  • 모든 생성자의 공통 부분을 instance initializer block에 넣어줌

class InstanceInitializerBlockSuper {
public InstanceInitializerBlockSuper() {
System.out.println(“InstanceInitializerBlockSuper”);
}
}

public class InstanceInitializerBlockTest extends InstanceInitializerBlockSuper {
private int id = 5;
{
if (id <10) id = 20;
else id = 100;
}

public InstanceInitializerBlockTest() {
System.out.println(“InstanceInitializerBlockTest.id=” + this.id);
}

public InstanceInitializerBlockTest(int id) {
System.out.println(“InstanceInitializerBlockTest.id=” + this.id);
this.id = id;
}

public int getId() {
return id;
}

public void print()
{
System.out.println(“StaticIntializerBlockTest.id=” + getId());
}

}

public class StaticInstanceInitializerBlockTest {

public static void main(String[] args) {
InstanceInitializerBlockTest i = new InstanceInitializerBlockTest();
i.print();
i = new InstanceInitializerBlockTest(30);
i.print();
}

}

InstanceInitializerBlockSuper // super 생성자 이후에 실행
InstanceInitializerBlockTest.id=20 // instance block 호출되면서 20으로 셋팅 
id=20
InstanceInitializerBlockSuper // super 생성자 이후에 실행
InstanceInitializerBlockTest.id=20 // instance block 호출되면서 20으로 셋팅된후 this.id = id를 통해서 30으로 셋팅
id=30

https://stackoverflow.com/questions/12550135/static-block-vs-initializer-block-in-java

Constructor usage guideline

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);
}
}
// Output: New 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
}
}

default, public, protected, private

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

Access Levels
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