본문 바로가기

공부/자바 OOP

5월30일 - this() / static / final

This ()

생성자함수 추가, 생성자함수를 호출

 

package oop0530;

import oop0529.School; //어제 만든 School 클래스 끌어오기


public class Test01_This {

	public static void main(String[] args) {
		
		School sch = new School(); //import가 없으면 에러
		
	}//main end
}//class end

1) School 클래스의 접근제어 : public

import로 oop0529패키지 내에 있는 School 클래스를 불러온 것이다.

School 클래스의 접근제어가 public인 경우 접근가능하다.

 

2) School 클래스의 접근제어 : package

같은 package안에 있는게 아니라면 접근 불가능하다.

 

3) School 클래스의 접근제어 : 없을때

에러가 생기며 접근 불가능하다.

 

import oop0529.* <-oop0529패키지의 모든 클래스를 불러오겠다라는 뜻.

 

생성자는 클래스 이름과 같다.

 

함수간의 호출이 가능하다

 

1) 생성자메소드가 생성자메소드를 호출할 수 있다.

그러나 이름을 불러다 쓰지 말고 내가 나를 부르는 것이므로 this를 사용해서 호출

 

public Sungjuk(){
	//생성자함수가 생성자함수를 호출할 수 있다.
	this("박영선"); //에러 없음
	Sungjuk("박영선"); //에러	
}

 

2) 생성자메소드를 호출할 때는 호출하는 첫 줄에서 해야한다.

public Sungjuk(int kor, int eng, int mat){
	this();//생성자가 자신의 생성자함수를 호출할 때 쓴다.
	this.kor = kor;
	this.eng = eng;
	this.mat = mat;
}
	
public Sungjuk(int avg){
	this.avg = avg;
	//this(10,20,30); // 에러: 생성자함수를 호출할 때는 호출하는 첫 줄에서 한다. 
}    

 

3) 생성자메소드에서는 일반메소드를 호출할 수 있다.

단, 일반메소드에서 this 쓸 수 없다.

this라는 명령어는 생성자메소드에서만 쓰는 것이다. 자기들 끼리만

public Sungjuk(int kor, int eng, int mat){
	this();//생성자가 자신의 생성자함수를 호출할 때 쓴다.
	this.kor = kor;
	this.eng = eng;
	this.mat = mat;
}
	
public Sungjuk(int avg){
	this.avg = avg;
	//this(10,20,30); // 에러: 생성자함수를 호출할 때는호출하는 첫 줄에서 한다.
	disp();
}
	
public void disp(){
	this(85); //에러
}

 

Static

stack 공간 -> 계속 리셋

static 공간 -> countinue

Static 변수, Static 메소드

메모리 생성도 1번, 소멸도 1번 -> 한번 생성되면 지속

new연산자를 이용해서 별도의 객체생성 없이 사용가능하다.

 

1)static의 특징을 적용하지 않은 경우

예제) 급여명세서

package oop0530;

class Sungjuk{
    //멤버변수
	private String name;
	private int kor,eng,mat;
	private int aver;
	
	//default constructor 생성자함수-클래스이름과 동일하게
	public Sungjuk(){
		//생성자함수가 생성자함수를 호출할 수 있다.
		//Sungjuk("손흥민"); 에러
		this("손흥민");
	}
	
	public Sungjuk(String name){
		this.name=name; //스트링형의 name과 멤버변수name이 겹치므로this를 이용해 멤버변수 지정
	}
	
	public Sungjuk(int kor, int eng, int mat){
		this(); //자신의 생성자함수 호출
		this.kor=kor;
		this.eng=eng;
		this.mat=mat;
	}
	
	public Sungjuk(int aver){
		this(10,20,30);
		this.aver=aver;
		//this(10,20,30); //세번쨰 생성자함수 호출. 에러남 
		//생성자함수를 호출할 때에는 첫줄에서 한다.
		
		disp(); //생성자함수에서 일반메소드 호출가능
	}
	
	public void disp(){
		//this(85); //에러
	}//disp() end
}//class end

public class Test02_This {

	public static void main(String[] args) {
		// this()
		// ->생성자함수가 생성자함수를 호출할 때 
		
	}//main() end
}//class end

출력결과
(주)솔데스크
사원번호: 1001
이름: 손흥민
총 지급액: 107
-------------------------------------

2) Static 특징을 적용한 경우

static 변수와 메소드는 이미 static 메모리에 값이 상주해 있기 때문에  
별도의 객체생성을 하지 않고도 직접 접근할 수 있다. 
Static 접근방법: 클래스명.static변수, 클래스명.static메소드()

 

Sawon two = new Sawon("1002","박지성",200);
int total = (int)(two.pay-(two.pay*two.TAX))+two.Sudang;		
		
System.out.println(two.COMPANY);
System.out.println("사원번호: "+two.saNum);
System.out.println("이름: "+two.name);
System.out.println("총 지급액: "+total);
Sawon.line();

 

2) Static 변수의 연산

static 변수도 연산이 가능하다.

System.out.println(kim.Sudang); //10
System.out.println(lee.Sudang); //10
		
kim.Sudang=kim.Sudang+1;
System.out.println(kim.Sudang); //11

lee.Sudang=lee.Sudang+1;
System.out.println(lee.Sudang); //12
System.out.println(kim.Sudang); //12

Sawon.Sudang=Sawon.Sudang+1;
System.out.println(Sawon.Sudang); //13

변수가 연산이 계속되어 값이 누적 된다.

static은 딱 하나밖에 안생기기 때문에

메모리 공간을 같이 쓰게된다. 있는 것을 재활용

공유공간의 개념. 그래서 연산하면 값이 동일한 데서 연산됨.

특정한 값을 공유해야할 때 static변수를 쓴다.

//static 변수
System.out.println(Math.PI);
//static 메소드
System.out.println(Math.abs(-3));
	
System.out.println(Integer.parseInt("5"));

 

Final

생성자, 상속 중요

변수, 함수, 클래스 확장 못하게 한 것.

변수: 변수의 상수화. 주로 static과 같이 사용한다.

클래스: 누군가의 부모클래스가 될 수 없다. 자식을 둘 수 없음. 상속받기 상속하기 둘 다 불가. //종단클래스

메소드: 더 이상 오버라이드(override, 재정의) 할 수 없다.

 

1) final 변수

final이라는 말을 앞에 붙여서 변수를 선언하면 상수. 고정불변한 값이 된다.

변경이 불가하게 제약을 걸어둔 값이다.

final로 b의값을 상수화 시켰으므로 b에 다른값넣어서 에러

2) final 클래스

종단클래스라고도 한다.

final class Animal {	
}
class Elephant extends Animal{ //에러메시지가 뜬다. final 클래스는 상속이 불가하다.
}

 

3) final 메소드

 

 

STRING

-교재 chap 7

종류

- String              : java.lang팩키지

- StringBuffer      : java.lang팩키지

- StringBuilder     : java.lang팩키지

- StringTokenizer  : java.util팩키지

 

1) String 

String name=new String("soldesk");
String str="Gone With The Wind";

1 length() - 글자갯수

2 charAt(n) - n번째 글자를 char형으로 출력

3 indexOf("") -""문자열의 순서값(index)

4 toLowerCase() / toUpperCase() - 전부 소문자/ 대문자로 변환

5 replace(old, new) - old를 new로 치환  

1.글자갯수
System.out.println(str.length());  //18
		
2. 0번째글자  'G' char형이라는 걸 알고잇어야함 
System.out.println(str.charAt(0));  //G
//마지막 글자 'd' 0부터 17까지
System.out.println(str.charAt(17));  //d
System.out.println(str.charAt(str.length()-1)); 
//17도 맞지만, 총 글자수의 -1한 것이 마지막 글자번수이므로
		
3. "G"문자열의 순서값(index)
System.out.println(str.indexOf("G"));  //0
//중복되는 문자열이면 처음 문자열의 인덱스 반환
System.out.println(str.indexOf("e"));  //3
//없는 문자열이면 -1반환
System.out.println(str.indexOf("K"));  //-1

4. 전부 소문자로 변환
System.out.println(str.toLowerCase());  //gone with the wind
//전부 대문자로 변환
System.out.println(str.toUpperCase());  //GONE WITH THE WIND

5. 'n' -> 'N' 으로 치환
System.out.println(str.replace('n', 'N')); //GoNe With The Wind

리턴값이 boolean형인 아이들

6 isEmpty() - 리턴값 boolean형 , 빈문자열이냐 아니냐

7 startsWith() / endsWith() - 리턴값 boolean형 , 앞/뒤에서부터 문자열 비교

8 equals -문자열 내용비교

6. isEmpty
if(str.length()==0){
	System.out.println("빈문자열이다");
}else{
	System.out.println("빈문자열이 아니다");
}//if end

출력결과
빈문자열이 아니다

//위의 조건문을 isEmpty()함수로 바꾸시오
if(str.isEmpty()){
	System.out.println("빈문자열이다");
}else{
	System.out.println("빈문자열이 아니다");
}//if end

출력결과
빈문자열이 아니다

7. 앞에서부터 문자열 비교
System.out.println(str.startsWith("Gone")); //true
//뒤에서부터 문자열 비교
System.out.println(str.endsWith("Wind")); //true
		
8. 문자열 내용비교
System.out.println("sky".equals("hi")); //false
		

9 subString() - 문자열의 일부분만 추출 (중요! 많이 쓰임 아주아주아중)

-자료형은 String이므로, String형으로 출력 " " !

-마지막 글자 출력할시, 맨 마지막 글자이기때문에 범위설정안해줘도 된다.

9. 문자열 일부분만 추출 

//6번째~마지막까지
System.out.println(str.substring(6));  //ith The Wind
//6번째~12-1번째까지
System.out.println(str.substring(6,12)); //ith Th

//첫번째글자 -> string형으로 출력 "G"
System.out.println(str.substring(0,1)); //G
//마지막글자 -> string형으로 출력 "d"
System.out.println(str.substring(17,18)); //d
System.out.println(str.substring(str.length()-1,str.length())); //d
System.out.println(str.substring(str.length()-1)); //맨마지막 글자니까 범위설정안해줘도 된당!

10 split("") -""안의 문자열을 기준으로 문자열 분리하기

-자료형 String[] : 1차원 배열

-만약, 기준으로 하는 문자열이 해당문자열에 존재하지 않을 경우, 분리안한채 그대로 출력함

//문자열 분리하기
String[] word=str.split("W"); //""안에 분리할 기준 문자열 삽입
for(int idx=0;idx<word.length;idx++){
	System.out.println(word[idx]);
}//for end

출력결과
Gone 
ith The 
ind

11 trim() - 문자열 좌우 끝에 있는 공백제거

11. 문자열 좌우 끝에 있는 공백제거
System.out.println("#"+"  s  k y   ".trim()+"#");  //#s  k y#

 


<연습문제>

문제 1) 이메일 주소에 @문자가 있으면 @글자 기준으로 문자열을 분리해서 출력하고
          @문자가 없다면 "이메일주소 틀림" 메세지를 출력하시오
      ->출력결과 : webmaster
                       soldesk.com

첫번째 내 답안
String email="danby1128@gmail.com";

for(int idx=0; idx<email.length(); idx++){
    if(email.indexOf("@")!=-1){
	   String[] word=email.split("@");
	   System.out.println(word[idx]);	
	}else{
	   System.out.println("이메일주소 틀림");
	}//if end		
}//for end

출력결과 -에러남
danby1128
gmail.com
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
	at oop0530.Test05_String.main(Test05_String.java:106)

두번째 내 답안 (선생님도움받고)
if(email.indexOf("@")!=-1){
	String[] word=email.split("@");
	for(int idx=0; idx<word.length; idx++){
		System.out.println(word[idx]);
	}//for end
}else{
	System.out.println("이메일주소 틀림");
}//if end

출력결과
danby1128
gmail.com

첫번째 내 답안 해석 ->

처음에 for문을 맨위로 적었을 때 email의 length는 20인데 , @기준으로 나뉜다는 if 문을 통과했을 때엔 두개로 나뉘는데 print하는 word의 수는 19가 되므로 2에서 막히는 것이었따.

답은 출력되었지만, 2에서 막혀서 오류가 났음. 

두번째 내 답안 해석 ->

선생님의 도움을 받아 첫번째 답안의 오류를 잡고 수정하였다.

@를 기준으로 두조각으로 나뉜다는 것을 포인트로 잡고, 먼저 if문을 돌리고 @이 있을 때, for문을 걸어주어 

두조각을 출력하도록 만들었다. 

@이 있는지 없는지 모르는 상태에서 for문을 돌리면 19조각을 움직여야하는 것이니 말이 안됐던 것이다.

 

선생님답안 ; indexOf를 변수 pos로 넣어주어 식을 간단히 적었다
int pos=email.indexOf("@"); 
	if(pos==-1){
		System.out.println("이메일주소 틀림");
	}else{
		System.out.println("이메일 주소 맞음");
		
                String id=email.substring(0,pos);
		String server=email.substring(pos+1);
		System.out.println(id);
		System.out.println(server);
	}//if end
    
출력결과
danby1128
gmail.com

해석 ->

indexOf를 다 적어도 되지만 이 함수를 변수 pos에 넣어주어 좀 더 간단히 만들어주었다.

선생님은 이메일주소의 id와 sever주소를 나누어 출력을 했다. 

pos의 기준은 @로 좌우로 나뉘기 때문에 id는 0부터 pos까지 / sever은 pos+1..?

 

문제 2) 주민번호를 이용해서 아래와 같이 출력하시오
생년월일 : 2015년 12월 30일
성별 : 여자
나이 : 4
주민번호 각 숫자의 전체 합 :

내 답안
String jumin="1512304123456";

String sex = jumin.substring(6,7);
	if(sex=="1"||sex=="2"){
		String year1 = 19 + jumin.substring(0,2);
		System.out.print("생년월일 : "+year1+"년 ");
		System.out.print(jumin.substring(2,4)+"월 ");
		System.out.println(jumin.substring(4,6)+"일");
	}else{
		String year2 = 20 + jumin.substring(0,2);			
		System.out.print("생년월일 : "+year2+"년 ");			
		System.out.print(jumin.substring(2,4)+"월 ");
		System.out.println(jumin.substring(4,6)+"일");
			
     switch(sex){
		case "1" : System.out.println("성별 : 남자"); 
		case "2" : System.out.println("성별 : 여자"); 
		case "3" : System.out.println("성별 : 남자");
		case "4" : System.out.println("성별 : 여자");
	}//if end
}//switch end
	
출력결과
생년월일 : 2015년 12월 30일
성별 : 여자

내 답안 해석->

난 성별을 기준으로 출력을 하려고 했다. switch에 다 붙여서 출력을 하려고 했는데 에러는 안났는데 출력이 안됐다.

다시 지우고 if문뒤에 switch문을 붙여 성별과 생년월일까지는 출력을 했지만, 이 식들은 자료형이 전부다 String이라서

나이가 계산이 안됐다.

따로 계산을 잡아주려니, 너무 많은 소스를 적기도 했고, 지저분하고 손이 안잡혓다ㅠ

그래서 여기까지만 하구, 선생님의 답을 기다렸다.

 

선생님답안
String jumin="1512304123456";
		
//성별코드 가져와서 정수형변환 "4" -> 4
int code=Integer.parseInt(jumin.substring(6,7));
	//System.out.println(code);
		
//주민번호에서 생년월일가져오기
int myYear= Integer.parseInt(jumin.substring(0,2));    //15
int myMonth=Integer.parseInt(jumin.substring(2,4));  //12
int myDate=Integer.parseInt(jumin.substring(4,6));     //30
		
//태어난 년도 완성하기 myYear
switch(code){
	case 1 :  
	case 2 : myYear=myYear+1900; break;
	case 3 : 
	case 4 : myYear=myYear+2000; break;
}//switch
		
System.out.print("생년월일 : ");
System.out.print(myYear+"년 ");
System.out.print(myMonth+"월 ");
System.out.print(myDate+"일 ");
System.out.println();
		
//성별
String gender="";
	switch(code%2){
		case 0 : gender="여자"; break;
		case 1 : gender="남자"; break;		
	}//switch end
		
System.out.println("성별 : "+gender);
		
//나이
int myAge=2019-myYear; //정수형시키는것이 포인트
	System.out.println("나이 : "+myAge);
		
//주민번호 합
1.subString 형
int hap=0;		
for(int a=0;a<jumin.length();a++){
	hap=hap+(Integer.parseInt(jumin.substring(a,a+1)));
}//for end		
System.out.println(hap);
2.charAt 형
int hap1=0;		
for(int a=0;a<jumin.length();a++){
	hap1=hap1+(((int)jumin.charAt(a))-48);  // char형으로 나오는 숫자에도 아스키코드가 있다
}//for end
System.out.println("주민번호 각 숫자의 전체 합 : "+hap1);		

출력결과
생년월일 : 2015년 12월 30일 
성별 : 여자
나이 : 4
주민번호 각 숫자의 전체 합 : 37

선생님 답안 해석->

이 문제의 포인트는 String형->정수형 변환

먼저 성별코드를 정수형으로 변환을 시켜주고, 생년월일에 해당하는 숫자를 불러냈다.

하지만 주민번호에서 년은 15로 불완전, 완전체로 만들어주기 위해 예전에 배웠던 switch구문을 이용해 

성별코드를 case에 집어넣고 1900,2000년도를 더해주었다.

성별은 똑같이 switch구문에 code를 %2해주어 여자 남자를 꺼냈다.

주민번호는 내가 했는데, 처음엔 정렬로 더해주려고 했다. 근데 에러먹고 안들어먹고 해서 쌤한테 물어봤더니

정렬은 안된다고 했고, 먼저 주민번호를 정수형으로 변환 후 하나씩 불러서 hap변수에 누적시키라 했다.

그래서 hap변수를 0으로 잡고, 정수형으로 변환후 한자리씩 더해주었다.

주민번호는 두가지 방법으로 가능하다

1. subString - 각 자리 수의 좌표를 (a,a+1) 해주어 누적시키기 

2. charAt     - 각 자리 수를 출력해낸다. 하지만 char형으로 나오는 숫자이기때문에 이 숫자엔 아스키코드가 있다.

                  0을 기준으로 48이므로 -48을 해줘야 정수형으로 출력이 된다.

끝!

 

문제 3) 파일이 이미지 파일(.gif .jpg .png) 인지 확인하시오
->출력결과
  파일명 : sky.png
  맞으면 "파일이 전송되었습니다"
  아니면 "파일을 다시 선택해주세요"
//파일명을 먼저 출력하기 .을 기준으로 

내 답안 이라고 부르고 짝의 도움을 받은 것
String filename="d:/java0514/workspace/sky.png";
		
String [] print=filename.split("/");
	for(int a=0;a<print.length;a++){
		if(print[a]==print[print.length-1]){
			System.out.println(print[a]);			
		}//if end			
	}//for end
	
    if(filename.endsWith(".gif")||filename.endsWith(".jpg")||filename.endsWith(".png")){
		System.out.println("파일이 전송되었습니다");
	}else{
		System.out.println("파일을 다시 선택해주세요");
	}//if end
    
    
출력결과
파일명 : sky.png
파일이 전송되었습니다

 

내 답안 해석->

처음에 내 생각은 파일명을 어떻게 모든 곳에 맞게 추출해낼까였다. substring으로 출력해낼수도 있지만 이건 이 식에만 

국한되어 있는 거니까. 몇번째 / 뒤에 있는 문자열 이런것도 생각했지만 코드는 떠오르지않았다.

짝의 도움을 받아 식을 완성했다.

먼저 /를 기준으로 split한다. 그럼 총 4조각이 나오고, 우리가 원하는 것은 맨 마지막 조각= 파일명

if문을 써서 배열의 idx값에 마지막조각일때, 누적시켜 출력해주었다. 이것이 파일명

파일명이 세가지 형식일때 파일 전송할지 말지 정하는것을 해야한다

이건 맨 뒤 수식명을 기준으로 하기때문에 endsWith를 써서 세가지 수식명을 넣어 || 연산자로 비교해주어 

if~else문으로 넣어주었다

끝!

 

선생님답안
//1단계 : 파일명.확장명 가져오기
int po=filename.lastIndexOf("/"); //21
filename=filename.substring(po+1); //"/" indexOf한 값의 뒷글자부터 필요하니까 +1해준다
System.out.println(filename); //"sky.png" 확장명이 대문자일수도 있기때문에, 먼저 전부 통일되게 바꿔준뒤 하면 쉽게 할수있따.
		
//2단계 : 확장명만 가져오기 ( . 말고)
int dot=filename.indexOf("."); // 위에서 filename=sky.png로 출력한 것에서 indexOf해줘서 3이 나옴
String ext=filename.substring(dot+1);
System.out.println(ext);
		
//3단계 : png || gif || jpg 인지 확인
ext=ext.toLowerCase(); //소문자로 전부 치환
	if(ext.equals("png")||ext.equals("gif")||ext.equals("jpg")){  //문자열 비교할 때엔 equals함수 이용
			System.out.println("파일이 전송되었습니다");
	}else{
			System.out.println("이미지 파일이 아닙니다");
	}//if end
    
출력결과
sky.png
png
파일이 전송되었습니다

'공부 > 자바 OOP' 카테고리의 다른 글

6월3일 - 상속  (0) 2019.06.03
5월31일 - Wrapper 클래스  (0) 2019.05.31
5월29일 - Class  (0) 2019.05.29
5월28일 - 메소드 + 정렬  (0) 2019.05.28
5월23일 - Method 메소드 ★매우 중요★  (0) 2019.05.23