본문 바로가기

Study/개발일지

[백엔드스터디WIL]3주차 학습일지

-  정규표현식 

-  다형성 

-  다양한 형변환

을 위주로 자바에대한 전반적인 복습을 진행

 

1. 정규표현식(Regular Expression)이란?

정규식은 프로젝트 개발에 있어서 빠지지 않고 사용되는 부분으로 "특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어"라고도 표현되는데요. 정규표현식은 이메일, 휴대폰 번호, 주민번호 등의 형식이나 비밀번호 같이 입력값이 정해진 형식에 맞는지 검증해야 할 때 유용하게 사용됩니다.

 

정규표현식을 사용할 때 이해를 하고 사용하기보다는 그냥 필요한 정규식을 찾아서 복사 붙여 넣기 하여 사용하는 경우가 많은데요.

앞서 이야기한 것처럼 개발에 있어서 빠지지 않고 사용되는 부분이기 때문에 한 번쯤 제대로 이해해두고 사용하면 수정이 필요할 때나 정규식 관련 오류가 발생했을 때 원인을 빠르게 파악하여 수정할 수 있습니다.

 

이어지는 내용에서는 정규표현식의 문법에 대한 내용과 정규식의 간단한 예시 및 실제로 사용되는 정규표현식에 대해서 알아보겠습니다.

 

 

 

2. 정규표현식 문법

Regular Expression Description
^ 문자열의 시작
$ 문자열의 끝
. 임의의 문자 1개를 의미
* 문자가 0번 이상 반복
+ 문자가 1번 이상 반복
? 문자가 0번 혹은 1번

 

Regular Expression Description
[ ] 문자의 집합 범위를 의미
[0-9] 숫자 0부터 9
[a-z] 알파벳 a부터 z
[a-zA-Z] 알파벳 a부터 z + 알파벳 A부터 Z
[a-zA-Z0-9] 알파벳 a부터 z + 알파벳 A부터 Z + 숫자 0부터 9
[^a-z] 알파벳 a부터 z가 아닌 것
(앞에 ^ 가 붙어있을 경우 not을 의미)

 

Regular Expression Description
{ } 문자가 나오는 횟수를 의미
{x} 앞의 문자가 정확히 x번 나옴
{x, } 앞의 문자가 적어도 x번 나옴
{x,y} 앞의 문자가 최소 x번 나오고, 최대 y번 까지 나옴

 

Regular Expression Description
( ) 소괄호 안의 문자를 하나의 문자로 인식(Grouping)
| or 조건
\ 확장문자 (*아래 추가 설명 참고)

 

Regular Expression Description
\b 단어의 경계
\B 단어가 아닌 것의 경계
\s 공백문자(whitespace)
\S 공백문자가 아닌 나머지 문자
(whitespace를 제외한 문자)
\w 알파벳이나 숫자, 언더바(_) 기호
\W 알파벳이나 숫자, 언더바(_) 기호를 제외한 문자
\d 숫자 ([0-9]와 동일)
\D 숫자를 제외한 모든 문자

*/

정규표현식에서 역슬래시(\)는 확장 문자를 의미하는데요.

역슬래시 다음에 일반 문자가 오면 특수문자로 취급하고, 역슬래시 다음에 특수문자가 오면 그 문자 자체를 의미합니다.

예를 들어서 알파벳이나 숫자를 나타내는 \w 같은 경우 Java에서 \ 자체를 특수문자로 취급하기 때문에 \\w와 같이 작성해야 합니다.

/*

(해당 부분은 아래 예시에서도 한번 더 언급하겠습니다.)

 

 

 

3. 간단한 예시 및 실제로 사용되는 정규표현식

^[0-9]*$               // 숫자가 0번 이상 반복 
=> ^는 문자열의 시작, [0-9]는 숫자, *는 0번 이상 반복, $는 문자열의 끝 

^[a-zA-Z]*$            // 영문자가 0번 이상 반복
=> ^는 문자열의 시작, [a-zA-Z]는 영문자, *는 0번 이상 반복, $는 문자열의 끝

^([a-z]+[0-9]*)$       // 영어 소문자가 꼭 포함되어야 하며, 숫자가 있어도 된다.
=> ^는 문자열의 시작, [a-z]는 소문자, +는 1번 이상 반복, [0-9]는 숫자, *는 0번 이상 반복, $는 문자열의 끝

^([a-z]+[0-9]{0,3})$   // 영어 소문자가 꼭 포함되어야 하며, 숫자는 최소 0번에서 최대 3번까지 나올 수 있다.
=> 나머지 동일 + {0,3}는 최소 0번에서 최대 3번 까지 반복

(간단한 예시)

 

^\w+@\w+\.\w+(\.\w+)?$
// 이메일

^\d{2,3}-\d{3,4}-\d{4}$          
// 전화번호 (ex 02-1234-5678)

^01(?:0|1|[6-9])-(?:\d{3}|\d{4})-\d{4}$    
// 휴대폰번호 (ex 010-1234-5678 | 011-123-4567)

^\d{6}\-[1-4]\d{6}$
// 주민번호

^\d{3}-\d{2}$
// 우편번호 (ex 123-45)

(실제로 사용되는 정규식)

 

^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$
// 최소 8자리에 숫자, 문자, 특수문자 각 1개 이상 포함

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$
// 최소 8자리에 대문자, 소문자, 숫자 각 1개 이상 포함

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}
// 최소 8자리에 대문자, 소문자, 숫자, 특수문자 각 1개 이상 포함

// ?= 는 전방 탐색 기호로 (?=.*[a-z]) 소문자가 1개 이상 들어갔는지 확인하는 부분

(실제로 사용되는 비밀번호 정규식)

 

/*

한번 더 언급하자면 자바에서는 역슬래시(\) 자체를 특수문자로 취급하기 때문에 \d, \w로 쓰이는 부분이 java 내부에서는 \\d, \\w 가 되어야 정상적으로 동작합니다.

*/

 

자바 다형성(polymorphism)은 객체지향언어의 특징 중 하나입니다. 자바에서 하나의 객체나 메소드가 여러형태로 사용될 수 있는 다형성의 특징을 잘 알고 있지 않으면 시간이 지날수록 미궁에 빠지게 됩니다. 특히 자동 형변환 등 코딩의 편리성을 위해서 제공되는 기능들로 인해서 프로그램 실행은 문제없이 지나갈 수 있으나, 프로그램 소스코드를 가만히 들여다 보면 왜 이렇게 동작되는지 이해가되지 않을 수 있습니다. 여기에서는 이러한 다형성에 대한 개념과 예제를 살펴보도록 하겠습니다. 

 

 

   목차

  1. 다형성이란?
  2. 형변환(Casting) 및 사용예제
  3. 형변환(Casting)의 장점 및 instanceof 연산자

 

 

1. 다형성이란?

 

다형성이란 하나의 객체나 메소드가 여러가지 다른 형태를 가질 수 있는 것을 말합니다. 

 

자바에서 다형성을 나타내는 것으로는, 오버라이딩 오버로딩 그리고 상속받은 객체의 참조변수 형변환등이 있으며, 여기에서는 예제를 통해서 상속받은 객체의 참조변수 형변환에 대해서 알아보도록 하겠습니다. 

 

cf) 오버로딩과 오버라이딩에 대해서는 아래글을 참고하세요

 

2022.06.27 - [IT 개발/Java] - [Java] 자바 - 오버로딩과 오버라이딩 (Overloading vs Overriding)

 

[Java] 자바 - 오버로딩과 오버라이딩 (Overloading vs Overriding)

자바 - 오버로딩과 오버라이딩 (Overloading vs Overriding) 자바에서 오버로딩과 오버라이딩은 객체지향언어의 특성중 다형성에 해당되는것으로 간략한 예제와 함께 알아보도록 하겠습니다. 1. 오버로

kadosholy.tistory.com

 

 

 

2. 형변환(Casting) 및 사용예제

 

상속받은 객체에 대해서 형변환이 의미하는 것은, 객체에 속한 멤버들에 대한 사용범위가 달라진다는 것을 의미합니다. 

 

  • 업캐스팅(upcasting) : (자식클래스의 인스턴스에 대한) 자식클래스의 타입의 레퍼런스 변수를 부모클래스 타입으로 형변환 하는 것. (타입변환 구문 생략 가능, 자동 형변환 됨)
  • 다운캐스팅(downcasting) : (자식클래스의 인스턴스에 대한) 부모클래스 타입의 레퍼런스 변수를 자식클래스 타입으로 형변환 하는 것. (타입변환 구문 생략 불가, 형변환 타입을 명시해야됨)

 

 

부모클래스와 자식클래스간의 객체 생성에 따른 형변환

 

 

1) Person 클래스 정의 (부모클래스)

public class Person {
	
	String name;
	int age;
		
	public void speak() {
		System.out.println(name + ": 안녕하세요");
	}
}

 

2) Dancer 클래스 정의 (자식클래스)

public class Dancer extends Person {
		
	public void dance() {
		System.out.println(name + ": 춤을 춥니다");
	}
}

 

3) 객체 생성 및 실행

public class HelloWorld {
	public static void main(String[] args) {

		//==================================
		System.out.println("==== 예시1 ====");
		//==================================
		Person p1 = new Dancer();
		
		p1.name = "홍길동";
		p1.speak();
		// p1.dance();  // 사용불가 
		
		Dancer d1 = (Dancer) p1;	// 다운캐스팅
		d1.name = "이순신";
		d1.speak();
		d1.dance();
		
		//==================================
		System.out.println("==== 예시2 ====");
		//==================================
		Dancer d2 = new Dancer();
		
		d2.name = "제갈공명";
		d2.speak();
		d2.dance();
		
		Person p2 = (Person) d2;	// 업캐스팅 - (Person) 생략가능
		p2.name = "신사임당";
		p2.speak();
		// p2.dance();  // 사용불가
		
	}
}

 

 

this() 메서드는 자신이 속한 클래스 내부에 다른 생성자를 호출하는 명령이다. 만일 클래스 명이 A라면 A() 생성자를 호출하는 것이라고 생각하면 된다. 만일 this(3)이라면 A(3), 즉 int 데이터 하나를 입력받는 생성자를 호출하라는 말이 된다.
this()메서드를 구성할 때는 반드시 2가지 문법적 규칙을 지켜야 한다. 첫 번째는 생성자의 내부에서만 사용할 수 있다. 즉, 생성자의 내부에서만 또 다른 생성자를 호출할 수 있다는 말이다. 두 번째는 생성자의 첫 줄에 위치해야 한다. 이 둘 중 어느 하나라도 지켜지지 않으면 바로 오류가 발생한다.

다음 예제를 살펴보자. 클래스 A에는 2개의 생성자가 있다. 생성자가 2개이므로 객체를 생성하는 방법도 2개다. 첫 번째 생성자는 기본 생성자로 내부에는 1개의 출력문이 있다. 따라서 A a1 = new A()와 같이 객체를 생성하면 이 과정에서 첫 번째 생성자가 호출되고 그 결과 "첫 번째 생성자"라는 문자열이 출력된다. 두 번째 생성자로 객체를 생성하는 A a2 = new A(3)을 실행하면 일단 객체 생성 과정에서 두 번째 생성자가 실행된다. 이 생성자의 첫 번째 명령은 this()이고 이는 자신의 또 다른 생성자인 A()를 호출하라는 말이다. 따라서 먼저 첫 번째 생성자가 호출된 후 나머지 코드가 실행되므로 "첫 번째 생성자"와 "두 번째 생성자"가 모두 출력되는 것이다.

실습

class A {
    A() {
        System.out.println("첫 번째 생성자");
    }
    A(int a){
        this(); // 반드시 생성자의 첫 줄에 위치해야 함.
        System.out.println("두 번째 생성자");
    }
}
/*
void abc(){
this();            메서드에선 this() 메서드 사용 불가능
 */

public class jh {
    public static void main(String[] args) {
        // 객체 생성
        A a1 = new A(); // 첫 번째 생성자 호출
        System.out.println();
        A a2 = new A(3); // 두 번째 생성자 호출 (생성자의 내부에서 첫 번째 생성자 호출)
    }
}

결과

 

 

자바에서 문자 타입의 char를 정수 타입의 int로 변환하는 방법입니다.

 

1. 자동 형변환, 강제 형변환 (X)

char c = '1';
int n = c; // == int n = (int)c;

System.out.println(n); // 결과: 49

자동 형변환이나 강제 형변환으로 char를 int로 변경하면 문자 '1'의 아스키 코드인 49가 출력되어 올바른 방법이 아닙니다.

 

 

2. '0'을 빼주기 (ASCII code 사용) (O)

char c = '1';
int n = c - '0'; // == int n = (int)c - '0'; 49 - 48 = 1

System.out.println(n); // 결과: 1

아스키 코드 표를 살펴보면 문자 0 ~ 9는 48 ~ 57의 순서로 되어있습니다.

따라서 문자 '1'의 아스키 코드에서 문자 '0'의 아스키 코드를 빼주면 원하는 숫자 1을 얻을 수 있습니다.

 

 

3. Character.getNumericValue() (O)

char c = '1';
int n = Character.getNumericValue(c);

System.out.println(n); // 결과: 1

2의 방법을 사용해도 원하는 값을 얻을 수 있지만, 보기 좋은 코드는 아니라고 생각합니다.

자바의 라이브러리중의 Character.getNumericValue() 함수를 사용하면 같은 결과를 좀 더 깔끔한 코드로 얻을 수 있습니다.

728x90