현재 element 에서 이전 또는 이후 element 를 접근 하려고 할때 

previousSibling
nextSibling 

2가지 를 사용해서 가져오려고 하지만 html element 가 아닌 #text가 호출될때가 있다.

원인은 element 사이에 whitespace(공백)으로 인해서 값을 제대로 못가져오게 된다. 

아래 샘플 html 코드에서 현재 2번에서 3번을 접근하려고 할때

<li>
    <a id ="1" >test1</a>
    <a id ="2" >test2</a>
    <a id ="3" >test3</a>
    <a id ="4" >test4</a>
</li>

 

var temp = document.getElementById('2');
console.log(temp.nextSibling); // #text

nextSibling은 id값이 3인 element 를 접근 못하고 #text를 가져온다.

해당 문법을 정상적으로 사용하려면 아래처럼 공백을 제거해야된다.

 

<li>
  <a id ="1" >test1</a><a id ="2" >test2</a><a id ="3" >test3</a><a id ="4" >test4</a>
</li>

 

하지만 이런 방법은 좋은게 아니기 때문에 whitesapce(공백)을 무시하면서 다음 element를 접근하는 

nextElementSibling 을 사용하면 된다. 

var temp = document.getElementById('2');
console.log(temp.nextElementSibling); // <a id ="3" >test3</a>

그럼 공백이 있어도 다음 element를 접근하고

형제 엘리먼트가 더이상 없을때 null을 return한다. 

 

jxl은 2003년 엑셀 파일까지만 지원해주기 때문에

아래 코드처럼 jxl 라이브러리 활용하여 Workbook 생성시 

import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

public String inputFIle(MultipartFile xlsxFile) throws BiffException, IOException {

        Workbook wb = Workbook.getWorkbook(xlsxFile.getInputStream());  <--에러 발생지점
        Sheet sheet =  wb.getSheet(0);

 

'Unable to recognize OLE stream' 에러 발생한다면

엑셀 파일 Excel 97 - 2003 서식 파일 (*.xlt) 이 아니여서 그렇다. 

확장자 .xlsx 는 jxl 라이브러리로 엑셀 접근이 어렵다.

대체 방안1.  POI 라이브러리 활용

대체방안 2. 엑셀 다른이름으로 저장 > 파일 형식 : Excel 97 - 2003 서식 파일 (*.xlt) 선택  저장 후 재진행

 

 

파일은 그대로 남겨두고 내용만 비우고자 할때

cat /dev/null > 해당파일

실제 예) 

cat /dev/null > catalina.out

당장 파일을 삭제 할 수 없고 용량이 커서 vi로 열어서 내용을 비우기 어려운 경우

해당 방식으로 내용을 비워주면 된다.

 

 

'프로그래밍 > 리눅스(Linux)' 카테고리의 다른 글

크론탭 (crontab) 설정  (0) 2022.02.03

 

크론탭 리눅스 환경에서 특정 주기로 반복해서 동작이 필요할때 사용한다. 

java의 스케줄러,  sql event 와 유사하다.

1시간마다 또는 특정 요일에 실행시키고 싶을때 활용하면 된다.

(쓴이는 오래된 log 삭제로 디스크 용량 유지 목적으로 사용 했다.) 

우선 실행할 스크립트를 작성 했다고 가정 하고 진행한다. 

 

[chron 텝 명령어]

설정 :  crontab -e
읽기 :  crontab -l
삭제 :  crontab -r

위와 같은 형태로 크론탭(crontab) 을 설정한다.

먼저 cmd 창에 crontab -e 치면

vi 환경처럼 빈 text 작성 공간이 나오고 i 를 누르고

아래와 같은 규칙으로 작성하면 끝난다.

* * * * * sh /home/test.sh

앞에 5자리 설정값의 의미는 아래처럼 이해하면 된다.

분,시간, 일, 월, 요일
*     *    *    *    *   명령어

매일 새벽 정각 6시에 test.sh 스크립트를 실행시키려면 

예) 0 6 * * * sh /home/test.sh

처럼 작성하면 정각 새벽 6시에 실행된다.

 

[스크립트 샘플]

스크립트 작성법 모른다면 아래 내용이 샘플 참고하라

#!/bin/sd  

#--------------------#
# 주석 샘플          #
#--------------------#

find /logs/* -mtime +6 -exec rm -f {} \;              # 파일을 지울때#
find /logs/ -type d -mtime +6 -exec rm -rf {} \;    # 폴더를 지울때#

[스크립트 설명]

" #!/bin/sd "  - 맨앞에 해당 구문을 작성해야 스크립트로 동작한다.

" # ~생략~ # " - #과 # 사이는 주석으로 활용 된다.

"find"(경로를 찾는 명령어) +

"경로"(원하는 작업 경로 지정) +

"-mtime +6"(현재 시간 6일전 이전 날짜) +

+ "rm"(지운다) +

"-f "파일을 지운다. OR "-r" 파일을 지운다.

  

잘 활용해서 노가다 -> 자동화 하나라도 더 만들자

'프로그래밍 > 리눅스(Linux)' 카테고리의 다른 글

리눅스 파일 내용 삭제  (0) 2022.05.10

 

Expected a value of type 'MaterialColor?', but got one of type 'Color'

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.black,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );

앱 테마색상 변경시 Expected a value of type 'MaterialColor?', but got one of type 'Color' 오류가 난다면 색상의 Type이 달라서 생긴 오류입니다.

해결법 

primarySwatch: -> primaryColor: 로 변경합니다.

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primaryColor: Colors.black,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );

 

오류 원인

색상 Type이 달라서 발생한 오류 입니다. 

Colors.black 이후 마우스를 올려두면 색상 Type: Color 이며

오류가 발생 안하는 Green 인 경우 마우스를 올려두면 Type: MaterialColor 입니다.

primarySwatch 속성에는 MaterialColor Type 만 가능하기 때문에 Color Type인 색상을 값으로 넣었기 때문에

발생한 문제 입니다.

속성을 primaryColor 는 Color 와 MaterialColor 모두 수용 가능하기에 원하는 색상으로 사용 가능합니다.

 

 

 

C#에서 using System.Net 를 사용하면 

FTP 접속해서 폴더 유무 확인이 가능합니다.

 

단계는

1. FTP로 접속할 IP, Port, 생성할 폴더명으로 경로를 파라미터로 WebRequest 를 초기화 해줍니다.

2. FTP로 접속을 위한 ID, Password 로 권한을 설정 하구요

3. FtpWebRequest 기능 중 해당 폴더의 하위 파일 목록을 가져오는(ListDirectory)를 대입 합니다.
   (해당 폴더의 하위 파일List를 가져와야 하는데 폴더 자체가 없으면 예외로 빠지기 때문에 해당 폴더의 유무를 알 수 있습니다.)

4. 그 다음 GetResponse() 함수로 FTP로 부터 결과 확인

 

4번 실행 후 예외로 빠지게 된다면

경로 마지막 폴더명 뒤에 / 표시를 안한경우 또는

이미 해당 폴더명으로 존재하거나 ID, Passsword 가 틀린 경우가 많으니 다시 한번 확인해 보세요.

 

# 아래 코드의 절반은 예외처리 내용이기 때문에 실제 기능 구현 코드는 7줄 정도 입니다.

 

코드 예시

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;

namespace WindowsFormsApplication2
{
    public class test
    {
        public void checkDirectoryExists()
        {
            string directory = "ftp://???.???.???.??:21/폴더1/";   //ftp://ip:포트/폴더명/; 

            FtpWebRequest requestFTPUploader = (FtpWebRequest)WebRequest.Create(directory);
            requestFTPUploader.Credentials = new NetworkCredential("ID", "PW");             //id, password

            var request = requestFTPUploader;
            request.Method = WebRequestMethods.Ftp.ListDirectory;

            try
            {
                using (var result = (FtpWebResponse)request.GetResponse())
                {
                    result.Close();  //정상 종료
                }
            }
            catch (WebException e)
            {
                FtpWebResponse response = (FtpWebResponse)e.Response;

                if (response.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
                {
                    Console.WriteLine("Does not exist");
                }
                else if (e.Status == WebExceptionStatus.ProtocolError)
                {
                    Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode);
                    Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription);
                }
                else
                {
                    Console.WriteLine("Error: " + e.Message);
                }
            }

        }

    }
}

 

 

해당 폴더가 존재한다면 GetResponse() 에서 True 를 반환하기 때문에

True 인 경우 FTP네트워크를 닫아 주고 해당 기능 구현을 마무리 했습니다.

 

FTP 폴더 유무 확인은 이런식으로 확인 가능하구요

반대로 FTP 폴더 생성을 하고 싶다면 아래 링크로 고고!

C# FTP 폴더 생성

 

'프로그래밍 > C#' 카테고리의 다른 글

C# FTP 폴더 생성 (FTP remote create directory)  (0) 2018.09.21
C# xml파일 읽기  (0) 2018.09.14
C# FileSystemWatcher 파일 감시 모니터링  (0) 2018.09.12

C#에서 using System.Net 를 사용하면 

FTP 접속해서 폴더 생성이 가능합니다. (mkdir)

 

단계는

1. FTP로 접속할 IP, Port, 생성할 폴더명으로 경로를 파라미터로 WebRequest 를 초기화 해줍니다.

2. FTP로 접속을 위한 ID, Password 로 권한을 설정 하구요

3. FtpWebRequest 기능 중 폴더생성(MakeDirectory)를 대입 합니다.

4. 그 다음 GetResponse() 함수로 FTP로 부터 결과 확인

 

4번 실행 후 예외로 빠지게 된다면

경로 마지막 폴더명 뒤에 / 표시를 안한경우 또는

이미 해당 폴더명으로 존재하거나 ID, Passsword 가 틀린 경우가 많으니 다시 한번 확인해 보세요.

 

코드 예시

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;

namespace WindowsFormsApplication2
{
    public class test
    {
        public void FTPUpload()
        {                                                                      //ftp://ip:포트번호/폴더명/
            FtpWebRequest requestFTPUploader = (FtpWebRequest)WebRequest.Create("ftp://???.???.???.??:21/폴더1/");

            requestFTPUploader.Credentials = new NetworkCredential("ID", "PW");

            var request = requestFTPUploader;

            request.Method = WebRequestMethods.Ftp.MakeDirectory;

            try
            {
                using (var resp = (FtpWebResponse)request.GetResponse())
                {
                    resp.Close();
                }
            }
            catch (WebException e)
            {                
            }
           
        }

    }
}

 

 

정상적으로 폴더를 생성했다면 GetResponse() 에서 True 를 반환하기 때문에

True 인 경우 FTP네트워크를 닫아 주고 해당 기능 구현을 마무리 했습니다.

 

위 코드로 폴더를 생성시 계층적으로 단계별로 만들어야 합니다.

예를 들어 현재 FTP A폴더 내부가 비어 있는 상태에서

A폴더/B폴더/C폴더((ftp://~/A폴더1/B폴더/C폴더/) 디렉토리 구조를 만들기 위해서

A폴더/B폴더/C폴더/ 이렇게 한번에 진행하면 예외로 빠집니다.

단계적으로 기존 A폴더가 있는 상태에서 A폴더/B폴더/ 로 만든 다음

A폴더/B폴더/C폴더/로 만들어야 합니다.

 

'프로그래밍 > C#' 카테고리의 다른 글

C# FTP 폴더 유무 확인 (FTP remote Check Folder)  (0) 2018.09.21
C# xml파일 읽기  (0) 2018.09.14
C# FileSystemWatcher 파일 감시 모니터링  (0) 2018.09.12

C#에서 XML 파일을 읽어오려면

using System.Xml 에 있는 함수를 사용하면

간단하게 읽어 올 수 있습니다.

 

단계는

1. xmlDocument 생성자를 호출

2 .읽어올 파일 경로를 로드

3. node 단위로 List 로 변환 후 읽어 오시면 됩니다.

 

코드 예시

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;   //MessageBox.Show() 사용시 필요
using System.Xml;             //xml 사용시 필요

namespace WindowsFormsApplication
{

    public class xmlRead
    {

        private void Read()
        {
            string temp = "";

            XmlDocument xml = new XmlDocument();

            xml.Load("D:\\test\\config.xml"); //"D:\\test\\config.xml" == @"D:\test\config.xml" 

            XmlNodeList xmlList = xml.SelectNodes("/config");

            foreach (XmlNode xnl in xmlList)
            {
                temp += xnl["Age"].InnerText;
                temp += xnl["ID"].InnerText;
                temp += xnl["Pw"].InnerText;
                temp += xnl["Name"]["성"].InnerText;
                temp += xnl["Name"]["이름"].InnerText;
            }
            MessageBox.Show(temp);
        }


    } //class
} //nameSpace

 

 

 

[config.xml]

-<config>
    <Age>20</Age>
    <ID>ID</ID>
    <Pw>password</Pw>
    <Name>
        <성>홍</성>
        <이름>길동</이름>
    </Name>
</config>

<Name> 내부 Child <성> 의 값을 읽어오고 싶을때는 xnl["Name"]["성"].innerText 처럼 중첩해서 [] 형태로 지정해주면 됩니다.

 

 

FileSystemWatcher 는 특정 폴더 경로(디렉토리)의 모든 파일

파일이 생성되거나 변경되면 함수 호출을 해줍니다.

 

우선 사용법은

1. FileSystemWatcher 생성자 호출

2. 감시할 폴더 설정(디렉토리)

3. 감시할 항목들 설정 (파일 생성, 크기, 이름., 마지막 접근 변경등..)

4. 감시할 이벤트 설정 (생성, 변경, 삭제..)

5. FIleSystemWatcher 감시 모니터링 활성화

6. 감시할 폴더 내부 변경시 event 호출

 

위 내용을 코드로 구현하면 ...

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; // FileSystemWatcher 은 System.IO 안에 있습니다. using System.Windows.Forms; namespace WindowsFormsApplication { public class FileWatcher { string EqpDirPath = "D:\test\"; private void initWatcher() { watcher = new FileSystemWatcher(); //1. FileSystemWatcher 생성자 호출 watcher.Path = EqpDirPath; //2. 감시할 폴더 설정(디렉토리) // 3. 감시할 항목들 설정 (파일 생성, 크기, 이름., 마지막 접근 변경등..) watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Size | NotifyFilters.LastAccess | NotifyFilters.CreationTime | NotifyFilters.LastWrite; //감시할 파일 유형 선택 예) *.* 모든 파일 watcher.Filter = "*.*";

 

watcher.IncludeSubdirectories = true; // 4. 감시할 이벤트 설정 (생성, 변경..) watcher.Created += new FileSystemEventHandler(Changed); watcher.Changed += new FileSystemEventHandler(Changed); watcher.Renamed += new RenamedEventHandler(Renamed); // 5. FIleSystemWatcher 감시 모니터링 활성화 watcher.EnableRaisingEvents = true; } // 6. 감시할 폴더 내부 변경시 event 호출 private void Changed(object source, FileSystemEventArgs e) { MessageBox.Show(e.FullPath); } private void Renamed(object source, RenamedEventArgs e) { MessageBox.Show(e.FullPath); }

 

 

 

코드 상단 주석처럼  

FileSystemWatcher 은 using System.IO 를 선언해 주셔야 합니다.  

initWatcher() 함수를 실행시키면  

주석 번호대로 1~ 5번까지 initWatcher() 함수가 실행이 된 상태에서  

D:\test\ 해당 파일 경로에 파일 또는 폴더가 생기면 바로 Changed() 이벤트가 호출됩니다.  

호출될때 담겨지는 파라미터 FileSystemEventArgs e 에서 e.Fullpath 를 꺼내오면 

생성된 파일의 전체 경로를 가져 옵니다. 

  예) D:\test\새 텍스트 문서.txt  

이렇게 FileSystemWatcher 를 사용해서 해당 폴더를 실시간으로 감지 모니터링하는 기능을 구현 했습니다.  

 

다음 포스팅에선 이렇게 폴더를 감지해서  

FTP 파일 서버로 업로드까지 확장시켜 볼게요 

 

 

 

20150916




예외처리(exception handling)


예외처리 작성법

try{

}catch (Exception ex){
처리
}finally{
//예외 발생여부랑 상관없이 무조건 마지막에 실행
}




20150916




인터페이스(interface)


장점


개발시간 단축

표준화 가능

서로 관계없는 클래스들에게 관계를 맺어줌  309쪽

독립적인 프로그래밍 가능



자바는 다중상속이 안되는데 인터페이스를 사용하면 다중상속과 같은 기능을 구현 할 수 있다.



인터페이스 일종의 추상메서드

인터페이스도 스스로 인스턴스를 생성할 수 없다.

추상메서드 와 차이점

몸통을 갖춘 일반 메서드 또는 멤버 변수를 구성원으로 가질 수 없다.


추상메서드와 상수만 가진다.


작성법

interface 인터페이스이름 {

public static final 타입 상수이름 = 값;

public abstract 메서드 이름 (매개변수);

}


모든 맴버 변수는 public static final

모든 메서드는 public abstract

생략 가능 (이유:컴파일시 자동적으로 추가)


인터페이스는 인터페이스끼리만 상속이 가능

interface SuperCar extends car {}

다중 상속 가능

interface SuperCar extends car , car2 {}

인터페이스는 스스로 인스턴스를 만들 수 없어서 구현해주는 클래스를 만들어줘야 한다.


클래스와의 관계는 구현이라고

작성법

class SuperCar implements Moveable {

}


class SuperCar extend Car implements Moveable {

}








20150916



추상클래스(abstract class)


추상 클래스를 만드는 방법

abstract class Car {

//...

}

추상클래스는 인스턴스를 생성할 수 없다.

추상 메소드 없어도 class 앞에 abstract 를 붙이면 인스턴스 생성x

추상클래스도 생성자를 가지고 있다.


추상 메서드 선언부만 작성

abstract 리턴타입 메서드 이름();


상속받는 클래스에서 몸통 {} 부분을 작성함

자식클래스가 구현을 안하면 그 자식클래스도 추상클래스


메서드를 사용하는 쪽에서는 (메서드 이름, 매개변수 ,리턴타입 )만 알면 됨


추상 메서드를 선언하는 이유: 반드시 구현하도록 강요하기 위해서


책 293 page 처럼 공통되고 반드시 구현해야 하는 부분을 추상 메서드로 지정한다.





20150916


다형성(polymorphism)-매개변수의 다형성


매개변수 또한 다형적인 특징이 적용 됩니다.

예를 들어서 SuperCar, BusCar, SuvCar 클래스가 있고 운전자 클래스에서 어떤 차를 다리게 할지를 정하는 run 함수가 있는 코드를 보겠습니다.


class SuperCar{
	boolean r = false;
}
class BusCar{
	boolean r = false;
}
class SuvCar{
	boolean r = false;
}
class Runner {
	run(SuperCar sc){
		sc.r = true;
	}
	run(BusCar bc){
		bc.r = true;
	}
}
class testtest {
	Runner rner = new Runner();
	SuperCar sc;
	BusCar bc;
	rner.run(sc);
	rner.run(bc);
}



Runner 클래스에 있는 run 함수의 매개변수가 SuperCar 클래스 타입이면 SuperCar 타입의 매개 변수만 올 수 있습니다. 그래서 다른 차를 달리게 하고 싶으면 매개변수를 바꿔서 오버로드 해서 차의 종류 만큼 만들어 줘야 하는 불변함이 있습니다.

그런데 모든 차의 공통된 부모 클래스를 상속 받으면 이런 불변함을 해결 할 수 있습니다.



class Car {
	boolean r = false;
}

class SuperCar extends Car{
	
}
class BusCar extends Car{

}
class SuvCar extends Car{
	
}
class Runner {
	run(Car car){
		sc.r = true;
	}
}

class testtest {
	Runner rner = new Runner();
	SuperCar sc;
	rner.run(sc);
}

이런식으로 공통 부모 클래스 Car를 상속받고 15번 줄에 있는 run의 매개변수를 Car 타입의 참조변수로 지정하면 하나의 run 함수로 모든 car 클래스를 상속받은 자식 클래스의 참조타입을 받을 수 있습니다.







'프로그래밍 > java' 카테고리의 다른 글

인터페이스(interface)  (0) 2015.09.16
추상클래스(abstract class)  (0) 2015.09.16
Java 다형성(polymorphism)-instanceof 연산자  (0) 2015.09.16
Java 다형성(polymorphism)  (0) 2015.09.16
java 메서드(method)  (0) 2015.09.12

20150916


다형성(polymorphism)-instanceof 연산자



상속 관계에서는 부모클래스의 참조변수로 자식클래스의 인스턴스를 참조 할 수 있다고 했습니다.
그렇다는 말은 참조변수 타입만으로는 실제 인스턴스 타입을 알 수 없습니다. 그래서 참조변수가 가지고 있는 실제 인스턴스를 알기 위해서  instanceof 연산자를 사용 합니다.

아래 코드로 설명 하겠습니다.
class Car {
.....
}

class SuperCar extends Car {
....
}

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

		Car car = new Car();

if(car instance of SuperCar){  //참조변수 car 가 superCar 와 상속관계이기 때문에 true 를 반환합니다.
      System.out.println("참조변수 car 는 SuperCar 와 상속 관계입니다.");
}
		
	
c = sc; //형변환 생략가능 
sc = (SuperCar)c;  //형변환 생략할 수 없다.		
	}
}
14번if(car instanceof SuperCar){...}  //car 는 Car 클래스의 참조변수 입니다.

왼쪽에는 참조변수 오른쪽에는 타입(클래스명)이 피연산자로 위치하고 결과는 boolean 값으로 true, false 중에 하나를 반환합니다.

instanceof 오른쪽에 있는 피연산자 SuperCar 클래스와 이클래스가 상속받는 모든 부모 클래스와 왼쪽에 있는 참조 변수 타입과의 상속관계를 비교해서 일치하는 클래스가 있으면 형변환이 가능하기 때문에 true 를 반환합니다.


'프로그래밍 > java' 카테고리의 다른 글

추상클래스(abstract class)  (0) 2015.09.16
Java 다형성(polymorphism)-매개변수의 다형성  (0) 2015.09.16
Java 다형성(polymorphism)  (0) 2015.09.16
java 메서드(method)  (0) 2015.09.12
Java 변수(Variables)  (0) 2015.09.12

20150916


다형성(polymorphism)


다형성을 알기 위해서는 상속에 대한 개념을 알고 있어야 합니다.

우선 자바에서 다형성은 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있게 하므로써 다형성을 나타냅니다.

즉 '여러 가지 형태를 가질 수 있는 능력' 을 의미합니다.

그러니깐 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조 할 수 있도록 한 겁니다.


car 클래스와 car 클래스를 상속받는 SuperCar 클래스로 예를 들면

아래 코드와 같이 


class Car {

	int speed = 10;
	void speedUp(){
		++speed;
		System.out.println("car 에서 speed:" + speed + "입니다.");
	}
}

class SuperCar extends Car {

	int speed = 9;
	int model = 2;
	boolean booster = false;
	void speedUp(){
		speed += 2;
		System.out.println("supercar에서 speed:" + speed +  "입니다.");
	}
}

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

		Car c = new Car();
		SuperCar sc = new SuperCar();
		Car c2 = new SuperCar();
		
		System.out.println(sc.model); //2   출력됨
	//	System.out.println(c2.model); // 오류남 변수 model를 사용 할 수 없다.

        System.out.println(c.speed);  //10 이 출력됨
		System.out.println(sc.speed); // 9 가 출력됨
		
		c.speedUp();  //car 에서 speed:11입니다. 가 출렴됨
		c2.speedUp(); //supercar에서 speed:12입니다. 가 출력됨
	}
}

Car 클래스 와  SuperCar 클래스 두 클래스의 인스턴스를 생성하고 사용하기 위해서 24번 25번 줄처럼 Car c = new Car(); 이런식으로 인스턴스 타입과 참조변수의 타입을 일치해서 사용하는건 아시죠? 그런데 여기서 Car 클래스와 SuperCar 클래스 처럼 서로 상속 관계는 Car c = new SuperCar(); 이런식으로 참조가 가능합니다.

그럼 Car c = new Car(); 와 Car c = new SuperCar(); 의 차이를 설명하자면

왼쪽의 참조변수 타입이 가지고 있는 맴버 변수만 사용이 가능합니다. 쉽게 말해서

car 클래스 맴버의 수는 2가지를 가지고 있고 CarSuperCar클래스는 상속받은 2개 와 자신이 가지고 있는 int model, boolean booster 를 총 더한 4가지고 가지고 있습니다.

Car c = new SuperCar(); 를 예를 들면 참조변수가 c 는 Car 클래스가 가지고 있는 맴버변수 2개만 사용 가능합니다. 그래서 car 는 가지고 있지 못한 SuperCar 의 변수는 사용을 할 수 없습니다.

25번 26번 줄에서 같은 인스턴스로 만들었지만 다른 참조변수 인 scc228번29번 줄에서 출력해보면 29번 줄은 참조변수 타입이 Car 라서 SuperCar 가 가지고 있는 model 변수를 사용 할 수 없어요. (오류가 납니다.)

그리고 25번26번 차이처럼 같은 부모클래스와 자식클래스가 둘다 가지고 있는 맴버변수는 참조변수 클래스에 있는 변수를 사용합니다.

하지만 31번32번 차이처럼 같은 부모클래스와 자식클래스가 둘다 가지고 있는 맴버함수는 좀 더 구체화(오버 라이딩)된 자식클래스의 함수를 사용합니다.


반대로 SuperCar sc = new Car(); 는 사용 할 수 없습니다.

위에서 설명 했듯이 참조변수의 타입 맴버 수 만 사용 할 수 있다고 했는데 이런 경우가 되면 사용 할 수 있는 범위중에서 사용 못하는 멤버가 들어가기 때문에 오류가 납니다.

예) sc.model  참조변수 타입 맴버에는 model 변수도 사용 가능 해야 하지만 인스턴스인 car 에는 model 변수가 없기 때문입니다.  

참조변수가 사용할 수 있는 맴버 수 는 인스턴스의 개수보다 같거나 작아야 합니다.






참조변수의 형변환


서로 상속관계인 클래스 사이에서는 참조변수도 형변환이 가능합니다.

자손 타입 -> 조상타입 (Up - casting) : 형변환 생략가능
조상타입 <- 자손타입 (Down-casting): 형변환 생략불가

아래 코드에서 처럼
class Car {
.....
}

class SuperCar extends Car {
....
}

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

		Car c = new Car();
		SuperCar sc = new SuperCar();
	
c = sc; //형변환 생략가능 
sc = (SuperCar)c;  //형변환 생략할 수 없다.		
	}
}

아래 코드에서 와 같이 car 와 SuperCar 처럼 상속 관계에서는 15번 줄처럼 형변환이 가능하다. 형변환을 하면 인스턴스의 멤버중 사용 할 수 있는 범위가 달라지게 됩니다.
sc 의 참조변수 타입이 SuperCar 라서 superCar 클래스의 변수를 모두 사용 가능한데 c 참조 변수로 형변환을 하게 되면 Car 클래스가 가지고 있는 변수들만 사용 가능합니다.  

참조변수 형변환은 참조변수의 타입이 변환되는 것이기 때문에 인스턴스는 변하지 않습니다.




+ Recent posts