상위 클래스인 추상클래스는 하위에 구현된 여러클래스를 하나의 자료형(상위 클래스 자료형)으로 선언하거나 대입할 수 있다. 추상 클래스에 선언된 메서드를 호출하면 가상 메서드에 의해 각 클래스에 구현된 기능이 호출된다. 즉 하나의 코드가 다양한 자료형을 대상으로 동작하는 다형성을 활용 할 수 있다.

 

아래는 추상클래스는 아니지만 다형성을 보여주는 예이다.

public class ShapeTest {

	public static void main(String[] args) {
		Shape1 s1,s2,s3; //s1, s2, s3은 모두 부모클래스인 Shape1 클래스 형을 갖는다
		s1 = new Shape1(); // s1, s2, s3 참조변수 모두에 Shape1 인스턴스가 부여된다.
		s2 = new Shape1();
		s3 = new Shape1();
		
		s1.draw();                //Shape Draw 출력
		s2.draw();                //Shape Draw 출력
		s3.draw();                //Shape Draw 출력
		
		s1 = new Rectangle1(); // s1, s2, s3 에 각각 Rectangle1(), Triangle1(), Circle1() 인스턴스가 부여된다.
		s2 = new Triangle1();
		s3 = new Circle1();    // 따라서 각 인스턴스의 클래스에 있는 메소드가 아래와 같이 출력이 된다.
		
		s1.draw();                //Rectangle Draw 출력
		s2.draw();                //Triangle Draw Draw 출력
		s3.draw();                //Circle Draw 출력
	}
}

class Shape1{
	protected int x, y;
	
	public void draw() {
		System.out.println("Shape Draw");
	}
}

class Rectangle1 extends Shape1 {
	private int width, height;
	
	public void draw() {
		System.out.println("Rectangle Draw");
	}
}

class Triangle1 extends Shape1{
	private int base, heigth;
	
	public void draw() {
		System.out.println("Triangle Draw");
	}
}

class Circle1 extends Shape1{
	private int radius;
	
	public void draw() {
		System.out.println("Circle Draw");
	}

 

그렇다면 자료형이 클래스 이름이라는 말은 무슨 뜻일까?

아래 소스를 통해 확인해보자

public class MyCounterTest {

    public static void main(String[] args) {
        MyCounter obj = new MyCounter(); 
        obj = new YourCounter();  /*참조변수 obj가 YourCounter 클래스를 참조할 수있게 변경하였지만 
                                    obj는 계속 MyCounter 형이기 때문에*/
        
        System.out.println("obj.value = " + obj.value);
        obj.inc(obj);              /*여기서 MyCounter형의 참조변수만 받는 MyCounter클래스의 inc메소드에
                                     들어가 작동한다.*/
        
        /*obj.incc(obj); <- 오류  // obj는 YourCounter 인스턴스로 변경되었어도 MyCounter클래스 형이기 
                                     때문에 YourCounter형의 참조변수만 받는 incc에는 접근 불가*/
       
        System.out.println("o3bj.value = " + obj.value);
    }
}

class MyCounter {
    int value;
    void inc(MyCounter ctr) {
        ctr.value = ctr.value + 1;
    }
}

class YourCounter extends MyCounter{
	void incc(YourCounter ctr) {
        ctr.value = ctr.value + 2;
    }
}

 

YourCounter는 MyCounter를 상속 받았으므로 상위 클래스인 MyCounter형으로 객체(참조변수)를 선언하여 사용할 수 있다.

 

참고로, 인스턴스 변환하여 메소드에 대입하는 과정을 간결하게 표현하는 방법이 있다. 방법은 아래와 같다.

class Human extends Animal {}

public class Animal{
	public static void main(String[] args) {
		Animal ani = new Animal();
		ani = new Human();
		ani.moveAnimal(ani);
		//ani.moveAnimal(new Human());  //<-- 바로 위 두줄을 이렇게 간단히 줄여 사용할 수 있다.
	}

	public void moveAnimal(Animal animal) {}
}
반응형

'JAVA > 개념' 카테고리의 다른 글

[자바] set함수, get함수  (0) 2021.03.30
[자바] 생성자  (0) 2021.03.30

자바에서 set함수, get함수를 왜 사용하는 것일까?

자바는 객체지향 프로그래밍 언어이다. 그 말인 즉슨, 함수를 통해 값을 전달하고 전달받는 방식을 사용한다는 것이다.

그렇기 때문에 서로 간의 관여가 많아 질 수 밖에 없다. 예를 들어 도서관에는 책마다 위치되는 구역이 정해져있다. 그 구역 데이터는 도서관 에서도 특정한 관리자들이 관리할 것이다. 그런데 도서관을 이용하는 학생이 그 위치 데이터를 마음대로 변경했다고 생각해봐라 얼마나 황당한 일인가? 그래서 정보의 은닉이 중요한 것이다. 아무도 모르게 내 마음대로 데이터를 변경하는 것이 아니라 관련 주체를 통해 변경함으로써 결함을 줄일 수 있다.

 

다음은 set함수와 get함수를 사용한 예시이다.

public class AccountTest {
	public static void main(String[] args) {
		Account at = new Account();
		at.setName("Tom");  //at이라는 객체를 통해 Tom이라는 이름을 set함수에 전달하고 있다.
		at.setBalance(10000); // 같은 방식으로 통장 잔고 전달
		System.out.println("이름은 " + at.getName() + " 통장 잔고는 " + at.getBalance() + "입니다. ");
	}
}
class Account{
	private int regNumber;     // 변수들을 private선언 하여 외부의 직접 접근이 불가능하여 정보의 은닉을 높이고 있다.
	private String name;
	private int balance;
	
	public String getName() {return name;} // 받은 이름을 반환한다. (이름 외에 불필요한 정보까지 조회되지 않는다는 장점)
	public void setName(String name) {this.name = name;} //String형의 값을 받으면 객체의 필드값을 받은 값으로 초기화한다
	public int getBalance() {return balance;}
	public void setBalance(int balance) {this.balance=balance;}
}

 

 처음 설명했던 내용과 위 코드에 달린 주석처리 설명으로 충분히 이해가 됐을 것이다.

 

그런데 변수가 많아지면 set함수 get함수가 엄청나게 많아질 것이다. 저렇게 일일이 함수를 선언하는 것이 얼마나 귀찮은 일인가? 이와 관련해서 코딩을 하는 사람이라면 알아야할 편의 기능이 있다.

 

먼저 위의 코드에서 아래와 같이eclipse에서 set함수 get함수 모두 지워보겠다.

 

 

그리고 나서 상단에 Source를 클릭하면

 

 

이런 창이 하나 뜰 것이다. 여기 나와있는 변수중에 set, get함수를 원하는 변수를 선택해서 아래 Generate를 누르면 

 

짜잔~ 한번에 알아서 뚝딱 만들어내는 모습!

넘나 편리한 것~

 

set함수 get함수 참 쉽죠?

 

반응형

'JAVA > 개념' 카테고리의 다른 글

[자바] 다형성  (1) 2021.03.31
[자바] 생성자  (0) 2021.03.30

생성자는 기본적으로 필드 초기값을 설정하는 용도로 사용한다.

그리고 생성자는 다음과 같은 특징을 갖는다.

1. 생성자명은 클래스명과 같아야 한다.

2. 리턴 값을 정의하지 않는다.

3. 객체가 생성될 때 호출된다.

아래는 생성자 사용의 예시이다.

설명은 주석처리 해놓았다.

public class CircleTest {

	public static void main(String[] args) {
		Point p = new Point(25, 78);
		Circle c = new Circle(p, 10);  // c라는 객체(이름이 c인 원(Circle))를 생성하면서 생성자를 통해
		System.out.println(c);         // 중심점(p), 반지름(10)을 전달하여 필드값을 초기화해주고 있다.
	}
}

class Point{
	private int x, y;
	
	public Point(int a, int b) {
		x=a;
		y=b;
	}

	@Override
	public String toString() {
		return "Point [x=" + x + ", y=" + y + "]";
	}
}

class Circle{
	private int radius;
	private Point center;
	
	public Circle(Point p, int r) { //p와 r을 받아 해당 객체의 필드값을 초기화 해준다.
		center = p;
		radius = r;
	}
	
	@Override
	public String toString() {
		return "Circle [radius=" + radius + ", center=" + center + "]";
	}

객체 하나하나는 고유의 특성을 갖는다 예를 들면 어떤 사람의 이름, 나이, 키, 몸무게 등 그 객체가 갖는 특정 값들을 생성자를 통해 편리하게 초기화 할 수 있다는 면에서 유용하다.

반응형

'JAVA > 개념' 카테고리의 다른 글

[자바] 다형성  (1) 2021.03.31
[자바] set함수, get함수  (0) 2021.03.30

자바에서 어떤 문자열을 저장하여 사용하고 싶을 때

String str = "abcdef";

와 같이 할 것이다. 원래는

String str = new String("abcdef"); 가 정확한 선언이지만 자바는 편의상 위의 문장처럼 선언하는 것을 허용하였다.

String이라는 클래스 이름으로 변수선언을 하였기에 str은 사실 참조변수가 되는 것이다.

 

그렇기 때문에 저 str이라는 객체 혹은 참조변수로 String클래스의 메소드를 사용할 수 있다.

이제 그 메소드들을 소개해보겠다.

 

isEmpty()

해당 변수가 비어있는지를 Boolean형으로 반환한다.

String a = "";
String b = "bbb";
System.out.println(a.isEmpty());
System.out.println(b.isEmpty());
true
false

 

equals()

두개의 문자열이 서로 같은지 true or false로 반환하는 메소드이다. 누군가는 이렇게 생각할 수 있다. "비교 연산자 ==를 사용하면 비교할 수 있잖아?" 다음의 예를 살펴보자

String aa = "world";
String bb = "world";
String cc = new String("world");

System.out.println(aa==bb);
System.out.println(bb==cc);
System.out.println(bb.equals(cc));
true
false
true

왜 이런 결과가 나온 것일까?

자바는 변수선언 형식의 String의 객체 생성을 통해 생성된 값(world)이 같으면 중복해서 주소를 생성하지 않는다.

그렇기 때문에 bb라는 객체를 생성할 때 이미 선언된 객체 aa의 값의 주소를 재활용하여 부여한 것이다.

 

하지만 new로 생성한다는 것은 무조건 다른 하나의 주소를 생성하라는 의미가 된다. world라는 같은 값이더라도 다른 주소를 생성하여 부여한다는 것이다.

 

따라서 aa, bb, cc의 값은 같지만 주소는 cc만 혼자 다른것이다.

따라서 ==는 주소까지 같아야 true를 반환하고 equals는 주소는 달라도 값이 같으면 true를 반환한다.

 

 

indexOf()

특정 문자가 처음 시작되는 인덱스 값을 int형으로 반환한다.

해당 문자가 존재하지 않으면 -1을 반환한다.

String a = "abcdefabcdef";
System.out.println(a.indexOf("c"));
System.out.println(a.indexOf("g"));
2
-1

 

substring(int beginindex, int endindex)

괄호 안에 들어가는 숫자 사이에 위치하는 문자를 반환한다.

예를 들어 str.substring(2, 5); 라고하면 str에 있는 문자열에서 2번째문자부터 5번째 전까지(2~4위치의 문자열) 잘라서 반환한다.

String str = "World";
System.out.println(str.substring(2, 4));
rl

 

toUpperCase()

toLowerCase()

toUpperCase()는 해당 문자열을 전부 대문자, toLowerCase()는 전부 소문자로 바꿔준다.

String str = "World";
System.out.println(str.toUpperCase());
System.out.println(str.toLowerCase());
WORLD
world

 

 

trim()

문자열 앞뒤에 있는 공백을 제거해준다.(중간은 제외)

String str = "    World";
System.out.println(str.trim());
World

 

charAt(int index)

해당 위치의 문자를 char형으로 반환한다.

String str = "World";
System.out.println(str.charAt(3));
l

 

valueOf()

괄호안의 값을 String형으로 즉, 문자열로 변환한다. 

int a = 123;
int b = 456;
System.out.println(String.valueOf(a)+String.valueOf(b));
123456 //문자열로 변환되었기 때문에 숫자로서가 아닌 문자열로서 더해져서 붙은 모습

 

toCharArray()

문자열을 한 글자씩 쪼개 char 배열로 반환한다.

String str = "World";
char[] arr = str.toCharArray();
System.out.println(arr);
System.out.println(Arrays.toString(arr));
World
[W, o, r, l, d]

//Arrays.toString() -> 배열의 내용을 출력할 수 있다.

 

getBytes()

byte 배열로 반환한다.

String str = "World";
byte[] arr = str.getBytes();
System.out.println(Arrays.toString(arr));
[87, 111, 114, 108, 100]

 

split(String regex)

문자열을 파라미터 기준으로 찢어 String 형 배열로 반환한다.

String str = "Hello/World/abc";
String[] arr = str.split("/");
System.out.println(Arrays.toString(arr));
[Hello, World, abc]

 

equalsIgnoreCase()

문자열이 대문자, 소문자 구분없이 같은 문자열인지 확인

String str1 = "World";
String str2 = "world";
		
System.out.println(str1.equalsIgnoreCase(str2));
true
반응형

실수의 연산은 오차가 따른다. 예를 들어 보자.

System.out.println(1.6+0.1);

1.6+0.1을 자바 이클립스에서 실행 할때 몇이 나올 것 같은가? 1.7? 아니다.

1.7000000000000002

정확한 1.7이 나오지 않고 소수점 뒤에 작은 오차가 발생한다. 컴퓨터는 실수를 표현할 때 부동소수점 방식을 사용하기 때문이다.

하지만 걱정하지마라 자바에는 이를 해결해줄 클래스가 존재한다. 바로 BigDecimal이라는 클래스이다.

이는 java.math패키지에 존재하기 때문에 import선언을 해줘야한다.

이제 BigDecimal 클래스를 사용해보자

import java.math.BigDecimal;

public class Main {

	public static void main(String[] args) {
		BigDecimal e1 = new BigDecimal("1.6"); // 객체생성 후 데이터입력 시 ""를 사용하여 문자열의 형태로 입력
		BigDecimal e2 = new BigDecimal("0.1");
		System.out.println(e1.add(e2));        //덧셈
		System.out.println(e1.subtract(e2));   //뺄셈
		System.out.println(e1.multiply(e2));   //곱셈
		System.out.println(e1.remainder(e2));  //나눗셈
	}
}
1.7
1.5
0.16
0.0

 

반응형

제목과 같이 숫자를 문자로 형변환 해주는 메소드 이다.

 

정수형은 integer.toString()

실수형은 Double.toString() 의 형태로 사용할 수 있다.

 

public static void main(String[] args) {
		int a = 2;
		int b = 2;
		System.out.println(a+b);
		System.out.println(Integer.toString(a)+b);
	}
4
22

 

출력란을 보면 첫번째 출력은 숫자 2와2를 더한 4가 나온것을 확인할 수 있고 두번째는 22로 되어있는데 이는 숫자 22가 아니라 문자"2"와 숫자 2가 붙어있는 모습이다. a를 문자열로 형변환 해주었기 때문이다.

 

 

 

 

 

 

 

 

 

반응형

Math.max, Math.min 은 Math클래스 소속 메소드이며 숫자 두개의 크기를 비교할 때 사용할 수 있다.

Math.max는 둘 중 큰값을, Math.min은 둘 중 작은 값을 반환한다.

 

System.out.println(Math.max(5, 10));
System.out.println(Math.min(5, 10));	
10
5

 

반응형

먼저 Random클래스를 살펴보자. 범위를 설정하면 범위 안의 난수를 뽑아내는 클래스이다.

활용 예제는 아래와 같다.

 

import java.util.Random;
public class Random2 {

	public static void main(String[] args) {
		Random ran = new Random();
		int num1 = ran.nextInt(100);
		double num2 = ran.nextDouble();
		System.out.println(num1);
		System.out.println(num2);
	}
}

 

이 클래스는 java.util 패키지에 속해있다. 따라서 import java.util.Random; 와 같이 import 선언을 해주어야한다. 

그리고 Random클래스를 활용하기 위한 객체를 생성(Random ran = new Random();) 해야한다.

int num = ran.nextInt(100); 는 0이상 100미만의 난수를 발생시켜 num1이라는 변수에 넣어줌을 의미하고

double num2 = ran.nextDouble(); 은 0이상1이하의 실수인 난수를 발생시켜 num2에 넣어준 것이다.

 

19
0.0581622972070579

 

그 결과 위와 같이 출력되었다.

 


 

그럼 이제 Math.random() 메소드를 살펴보자.

Math클래스는 수학관련 함수를 제공해주는 클래스로 java.lang패키지에 속해있기 때문에 따로 import를 안해줘도 된다. 그리고 모든 필드와 메소드가 static으로 선언되어 있기 때문에 객체를 생성하여 접근하지 않아도 된다. 그리고 Math.random() 메소드는 0이상 1이하의 난수만 발생시킨다는 것에 주의해야한다. 아래 예를 보자.

 

public class Random2 {

	public static void main(String[] args) {
		double num = Math.random();
		System.out.println(num);
	}
}

 

num이라는 변수에 Math.random()을 통해 난수를 넣었다.

뽑은 결과는 아래와 같다.

 

0.5962121869771372

 

 


 

 

둘 중 어느 것을 쓸 것인지는 개인의 취향에 따라 선택하면 될 것이다.

필자라면 Math.random() 을 사용할 것 같다. 그 이유는 객체 생성이 필요없고 0부터1사이의 실수인 난수라고 해도 곱셈연산으로 충분이 정수인 난수를 뽑아낼 수 있기 때문이다.

 

 

반응형

+ Recent posts