Dev/Java

[java] Calendar 클래스, Wrapper 클래스, Singleton, final

창문닦이 2019. 1. 24. 19:56

Calendar 클래스를 사용해서 만년 달력 만들기

import java.util.Calendar;

import java.util.Scanner;

public class CalendarA {

public static void main(String[] args) {

Calendar now = Calendar.getInstance();

Scanner sc = new Scanner(System.in);

int i, y, m, w, lastday;

do {

System.out.print("년도?");

y = sc.nextInt();

} while (y < 1);

do {

System.out.print("월?");

m = sc.nextInt();

} while (m < 1 || m > 12);

now.set(y, m - 1, 1);

w = now.get(Calendar.DAY_OF_WEEK);

lastday = now.getActualMaximum(Calendar.DATE);

// 출력

System.out.println(y + "년 " + m + "월");

System.out.println("\n  일 월 화  수 목 금 토");

System.out.println("------------------------------");

for (i = 1; i < w; i++) {

System.out.print("    ");

}

for (i = 1; i <= lastday; i++) {

System.out.printf("%4d", i);

w++;

if (w % 7 == 1) {

System.out.println();

}

}

if (w % 7 != 1) {

System.out.println();

}

System.out.println("------------------------------");

}

}


String의 다양한 메소드

public class Test1 {

public static void main(String[] args) {

String s1 = "서울,부산,대구";

String ss[] = s1.split(","); //split메소드 : ,를 기준으로 내용을 잘라서 ss배열에 저장해라

for(String s:ss){

System.out.print(s + " ");

}

String s2 = "seoul";

String s3 = "Seoul"; //s2 s3의 주소는 상이함. 영대소문자 구분.

System.out.println(s2.equals(s3)); //false

System.out.println(s2.equalsIgnoreCase(s3)); //true

//equalsIgnoreCase메소드 : 대소문자 구분하지 않고 내용만 비교

String s4 = "abc.def.hij";

//index      01234567890

System.out.println(s4.indexOf(".")); // 3 : "."이 나오는 index값을 반환함

System.out.println(s4.lastIndexOf(".")); // 7 : "."이 나오는 마지막 index값을 반환함

System.out.println(s4.indexOf("deff")); // -1 : 해당하는 값이 없으므로 -1 반환.

      //def 입력시 제일 첫번째 인덱스인 4반환

System.out.println(s4.indexOf("x")); //a != -1 이면 반복문실행 등으로 많이 이용

String s5 = "우리나라 대한민국 좋은나라 대한민국";

//String s6 = s5.replaceAll(regex, replacement); regex: 정규화표현식. '//s' 공백과 같은 특수기호

String s6 = s5.replaceAll("대한", "大韓"); //replace는 문자만 가능. replaceAll은 정규화표현식도 사용가능

System.out.println(s6);

String s7 = "  a b  c ";

System.out.println(s7);

System.out.println(s7.trim()); //맨왼쪽과 맨오른쪽의 공백 제거

System.out.println(s7.replaceAll(" ", "")); //공백을 null로 바꿔라

System.out.println(s7.replaceAll("\\s", "")); //공백을 null로 바꿔라

//web에서는 enter를 인식못함. <br>로 작성.//이 때 replace메소드 많이 쓴다.

char ch = "abcdefg".charAt(2); //string변수는 만들지 않았지만 String값에서 2번에 있는 한개의 문자를 추출해라

//idx      0123456

System.out.println(ch); //c

System.out.println("abcdefg".startsWith("abc")); //true. String이 "abc"로 시작여부. //ajax의 제시어 때 나옴.웹의 연관검색어

System.out.println("abcdefg".startsWith("abd")); //false.

System.out.println("abcdefg".length()); //7

//사전식 배열 정렬.(ASCII값의 차) 가나다순으로

String s8 = "abcdefg";

String s9 = "abcefgh";

System.out.println(s8.compareTo(s9)); //-1

System.out.println(s9.compareTo(s8)); //1

}

}


String의 메소드를 활용한 계산기 만들기

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

public class Test2 {

public static void main(String[] args) throws IOException {

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

System.out.print("수식[3+5] : " ); //15+25  idx:01234

String str = br.readLine();

str = str.replaceAll("\\s", ""); //공백 입력 할 수 있으므로 제거.

/*

String[] o = {"+","-","*","/"}; //영구적으로 배열저장.

for(String op : o){

}

*/

// 위에 3줄과 같은 코딩. 배열생성과 동시에 for문 작성.

// 배열을 만들었는데 이름이 없는 것. 비교하고 없애버리겠다.

// 주소가 없어서 찾아갈 수 없다. garbage collector가 수집

for(String op :new String[]{"+","-","*","/"}){

int pos = str.indexOf(op);//15+25 라면 pos = 2 저장. 찾으려는 게 없으면 -1 저장

if(pos>-1){ //연산자가 없을경우의 반환값이 -1

int num1 = Integer.parseInt(str.substring(0,pos)); //substring은 마지막인덱스-1

int num2 = Integer.parseInt(str.substring(pos+1)); //pos+1부터 끝까지의 숫자를 int형으로 바꿔서 저장

int result = 0 ;

char oper = str.charAt(pos); //2

switch(oper){

case '+':

result = num1 + num2; break;

case '-':

result = num1 - num2; break;

case '*':

result = num1 * num2; break;

case '/':

result = num1 / num2; break;

}

//System.out.printf("%d %c %d = %d", num1, oper, num2, result); //이대로 출력해라

String s = String.format("%d %c %d = %d", num1, oper, num2, result); //반환값을 string으로 만드는 것

System.out.println(s);

//return s; 반환값 String이므로 원하는 곳에 저장된 s를 불러서 사용.

}

}

}

}


두수[5,2]? 15,40 문자구분작업

연산자 ? + 연산자 입력

15+40=55 결과 출력

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.Scanner;

class TestTest{

public void print(String result){

System.out.println(result);

}

}

class Calc extends TestTest{ //상속관계 사용

private int num1, num2, r;

private char oper;

String result, str;

public void input() throws IOException{

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

System.out.print("두 숫자 입력[5,2] : " );

String str = br.readLine();

str = str.replaceAll("\\s", "");

String ss[] = str.split(",");

num1 = Integer.parseInt(ss[0]);

num2 = Integer.parseInt(ss[1]);

System.out.println("연산자?");//+,-,*,/

oper = (char)System.in.read();

}

public String calc(){

if(oper=='+'){

r = num1 + num2 ;

}else if(oper=='-'){

r = num1 - num2 ;

}else if(oper=='/'){

r = num1 / num2 ;

}else if(oper=='*'){

r = num1 * num2 ;

}else{

System.out.println("연산자 오류");

}

String result = String.format("%d %c %d = %d", num1, oper, num2, r);

return result;

//return String.format("%d %c %d = %d", num1, oper, num2, r);

}

}

public class Test3 {

public static void main(String[] args) throws IOException {

Calc ob = new Calc();

ob.input();

String r = ob.calc();

ob.print(r);

}

}


Wrapper class

자바형의 데이터는 2개 존재.

boolean, byte, char, short, int, long, float, double

레퍼런스(참조형) 데이터

Boolean, Byte, Character, Short, Integer, Long, Float, Double

양방향 통신이 되느냐

auto-Boxing : stack -> heap  stack 영역의 데이터가 heap 영역으로 넘어가는 것

auto-UnBoxing :heap -> stack


int a = 10; double b; b = a; 암시적형변환 잘들어감. b = (double)a; 명시적형변환 a = b; 안들어감 a = (int)b; 명시적형변환. 큰 데이터자료형을 넣기 위해선 반드시 명시적형변환 필수 --------------------------------------------- double과 int는 상속관계는 아니지만 이해하기 편하게 쓴 것 부모(b) - 자식(a) double이 더 크다 라고 생각. 부모 = 자식 O upcast 부모 = (부모)자식 O upcast 자식 = 부모 X 자식 = (자식)부모 O downcast upcast시점을 알아야 나중에 downcast할 때 활용이 가능

public class Test4 {

//n1 -> num1 , num2 -> n2 들어가는지 확인. 잘 들어간다!

public static void main(String[] args) {

int n1 = 10;

int n2; //쓰레기값

Integer num1; //null. Integer는 Wrapper class. class의 초기값은 null

Integer num2 = new Integer(20);

num1 = n1; //auto-Boxing

n2 = num2; //auto-UnBoxing

System.out.println(n1+":"+ num1); //10:10

System.out.println(n2+":"+ num2); //20:20

}

}


Calendar클래스. 자주 쓰는 메소드

현재 컴퓨터 시스템의 날짜 및 시간을 관리

import java.util.Calendar;

import java.util.GregorianCalendar;

public class Test5 {

public static void main(String[] args) {

//Calendar now = new Calendar();와 아랫줄은 의미가 같음

Calendar now = Calendar.getInstance(); //instance -> 객체를 사용해야만 쓸 수 있는 변수

//Calendar now = new GregorianCalendar();  // upcast

//부모                자식

//GregorianCalendar now1 = new GregorianCalendar(); GregorianCalendar의 부모클래스는 Calendar이므로

//부모클래스의 메소드 사용 가능

int y = now.get(Calendar.YEAR); //년

int m = now.get(Calendar.MONTH)+1;   //월. 0-11의 숫자를 가지고 있음

//꺼낼때는 +1 (넣어줄때는 월-1 해주면됨)

int d = now.get(Calendar.DAY_OF_MONTH); //일

int w = now.get(Calendar.DAY_OF_WEEK); //주의수(1-7: 1일요일 ~ 7토요일)

char[] yoil = {'일','월','화','수','목','금','토'};

System.out.println(y + "-" + m + "-"+ d + "-" + yoil[w-1]);

//달의 마지막날

int firtDay = now.getActualMinimum(Calendar.DATE); //1. 매번 똑같으니 그냥 숫자 1쓰는게 나음

int lastday = now.getActualMaximum(Calendar.DATE); //매달 말일은 다름

System.out.println(firtDay + " : " + lastday);

//Calendar클래스가 있으니까 매달 말일이 언젠지 계산할 필요가 없다.

System.out.printf("%tF \n",now); //2018-12-12

System.out.printf("%tT \n",now); //14:04:54

System.out.printf("%1$tF %1$tT \n",now); //2018-12-12 14:04:54. 1$는 뒤에 있는 인수가 하나니까 같은거로 써라

//사용자가 입력한 연도, 월, 일수

now.set(2019,10-1,10);//오버로딩된 메소드 많음. 집어넣을땐 -1해줘야 함(0~11까지 존재)

y = now.get(Calendar.YEAR);

m = now.get(Calendar.MONTH)+1;  

d = now.get(Calendar.DAY_OF_MONTH);

w = now.get(Calendar.DAY_OF_WEEK);

System.out.println(y + "-" + m + "-"+ d + "-" + yoil[w-1]); //내년10월10일은 목요일

}

}


Singleton

객체를 계속해서 생성하는 것이 아니라 하나만 생성하고 공유해 사용하는 방법이다.

Static, Call by reference : 이 구조를 갖는 객체를 singleton 객체라고 함.

class Sing{

private static Sing ob; //클래스의 초기값은 null. 이 상태에서는 null. static으로 만들었으므로 바로 메모리 할당.

public static Sing getInstance(){ //반환값이 자기자신. Call by reference

if(ob==null){

ob=new Sing();

}

return ob;

}

}

public class Test6 {

public static void main(String[] args) {

Sing ob1 = Sing.getInstance(); //static변수. getInstance 메소드 사용해서 생성

Sing ob2 = Sing.getInstance();

//Call by Reference

//주소를 서로 나눠씀. ob, ob1, ob2 모두 갖은 주소 가지고 있음. static 기능을 이용

//Singleton: static, call by reference와 이 구조를 모두 알아야 사용 가능

if(ob1 == ob2){

System.out.println("동일객체");

}else{

System.out.println("다른객체");

}

}

}


final을 붙일 수 있는 3가지 경우

멤버변수에 final을 붙이면 : 단 한번만 초기화가 가능

메소드에 final을 붙이면 : Override(재정의) 불가.

클래스에 final을 붙이면 : 상속 불가

final class Test{} -> public class Test7 extends Test{}  불가능!

class Test{ //Test클래스에 final붙으면 상속 불가

public static final double PI; //멤버변수

static{

PI = 3.141592;

}

public double area; //인스턴스 변수

public final void write(String title){ //메소드에 final붙어서 오버라이딩 불가

System.out.println(title+":"+area);

}

}

public class Test7 extends Test{

  부모클래스에 final이 붙어있으면 오버라이딩이 불가능하다.

@Override

public void write(String title) {

super.write(title);

}

public void circleArea(int r){

area= (double)r*r*PI;

}

public static void main(String[] args) {

Test7 ob = new Test7(); //객체생성

//PI = 100; 초기화된 값에서 변경 불가

ob.circleArea(10); //자식클래스 메소드

ob.write("원"); //부모클래스 메소드

}

}


자식클래스와 부모클래스

자식이 부모의 메소드를 override했다면 나에게 맞춰 메소드 내용을 바꾸고 싶기 때문에 진행한 것.

나의 의도가 들어간다 = 책에서는 보안영역이 강하기 때문에 호출을 어떻게 하더라도 자신의 결과를 돌려준다 표현.

오버라이드 메소드를 사용할 때, 부모클래스의 메소드로 꼭 사용하고 싶다면 자식메소드의 super.메소드명(); 로 호출하는 방법이 있음.

단, main문에서는 사용이 불가능 함.

class Parent{

protected int a = 10; //protected: 동일패키지안에서 사용가능

protected int b = 20;

public void write(){

System.out.println("Parent Class write()...");

System.out.println("a: "+ a + ", b: "+ b); //10,20

}

}

class Child extends Parent{

protected int b = 30;

protected int c = 40;

@Override

public void write() {

//super.write();//부모의 write 메소드 호출

System.out.println("Child Class write()...");

System.out.println("a: "+ a + ", b: "+ b+", c: "+ c); //10,20

System.out.println("super.b: " + super.b);

}

public void print1(){

System.out.println("Child Class print1() : write()호출..");

write(); //부모도 write메소드를 갖고있지만 나도 있으니까 내껄 호출

}

public void print2(){

System.out.println("Child Class print2() : super.write()호출..");

super.write();

}

}

public class Test8 {

public static void main(String[] args) {

Child ob = new Child();

ob.write(); //자신의 메소드 사용. a는 내거 없으니까 부모클래스에서 가져옴. a: 10,b: 30,c: 40

System.out.println("--------------------------------------------");

ob.print1();

System.out.println("--------------------------------------------");

ob.print2();     //부모의 메소드 사용. super 붙어있음

System.out.println("--------------------------------------------");

System.out.println("ob.b : " + ob.b); //부모클래스, 자식클래스 모두 존재하면 자기거 사용. b=30

System.out.println("((Parent)ob).b : " + ((Parent)ob).b); //자식을 부모클래스로 형변환시킴. upcast. b=20

//자식을 부모로 casting : upcast

System.out.println("--------------------------------------------");

ob.write(); //자식의 write메소드 호출

System.out.println("--------------------------------------------");

((Parent)ob).write();

부모클래스로 형변환을 했어도 메소드는 인스턴스 변수와는 다르게 자신의 메소드를 호출한다

메소드는 heap영역이 아니라 메소드 영역에 있기 때문에 접근 금지.(메소드 영역 보안 높음)

메소드는 upcast를 해도 무조건 자신의 것을 사용한다.

자식의 write메소드 호출

}

}


calendar를 활용한 만년달력 만들기

년도?2016 월?4 일?20 며칠 후? 100 만난날: 2016년 4월 20일 ㅇ요일 100일후: 2016년 7월 29일 ㅇ요일

import java.util.Calendar;

import java.util.Scanner;

public class Test9 {

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

int y, m , d, k, w;

char[] yoil = {'일','월','화','수','목','금','토'};

Calendar now = Calendar.getInstance();

do {

System.out.print("년도?");

y = sc.nextInt();

} while (y < 1);

do {

System.out.print("월?");

m = sc.nextInt();

} while (m < 1 || m > 12);

do {

System.out.print("일?");

d = sc.nextInt();

} while (d < 1 || d > 31);

System.out.print("며칠후?");

k = sc.nextInt();

now.set(y,m-1,d);

w = now.get(Calendar.DAY_OF_WEEK);

System.out.println("만난날: "+y + "-" + m + "-"+ d + "-" + yoil[w-1]+"요일");

now.add(Calendar.DATE,k);

int yy = now.get(Calendar.YEAR);

int mm = now.get(Calendar.MONTH)+1;  

int dd = now.get(Calendar.DAY_OF_MONTH);

int ww = now.get(Calendar.DAY_OF_WEEK);

System.out.println(k +"일 후: "+yy + "-" + mm + "-"+ dd + "-" + yoil[ww-1]+"요일");

}

}