추상 메소드를 포함하고 있는 클래스이다.
선언부만 있고 구현부는 없는 메소드
//추상 메서드를 하나라도 가지고 있으면
//클래스도 abstract키워드를 명시
abstract class AbClass{
//선언부 | abstract 키워드로 추상메서드임을 명시
public abstract void abTest(){
//구현부
}
}
추상 메소드만으로 이루어진 클래스를 의미하며, 인터페이스 안에 만들어지는 메소드들은 전부 추상메소드기 때문에 abstract키워드를 명시하지 않아도 된다.
인터페이스를 상속받으면(Implements) 반드시 모든 메소드를 오버라이딩하여 구현해야함
변수도 만들 수 있으나 잘 사용하지 않으며, 만들시 반드시 값을 지정해줘야 함
메소드가 구현되어있지 않기 때문에 객체를 직접 생성할 수 없고, 인터페이스를 구현한 구현체로 객체를 만든다.
//인터페이스를 상속받아 구현하는 구현체, 인터페이스는 구현체로 객체화 가능하다.
public class InterfaceImplements1 implements InterfaceTest{
//오버라이딩 해야할 메소드1
//오버라이딩 해야할 메소드2
//오버라이딩 해야할 메소드3
}
하나의 변수에 서로 다른 클래스를 구현한 객체를 저장할 수 있는 것 (일반적으로 상속관계에 한정)
//자기 타입으로 자신 객체 생성
InterfaceImplements1 it01 = new InterfaceImplements1();
InterfaceImplements2 it02 = new InterfaceImplements2();
//부모 인터페이스 타입으로 자식1 객체 생성
InterfaceTest it03 = new InterfaceImplements1();
//부모 인터페이스 타입으로 자식2 객체 생성
InterfaceTest it04 = new InterfaceImplements2();
자식 타입을 부모 타입으로 형변환 시키는 것
일반적으로 부모타입으로의 업캐스팅은 자동으로 이루어진다
부모 타입으로 업캐스팅을 하면 자식타입에서 새롭게 정의되거나 추가된 기능과 속성은 사용할 수 없기 때문에, 실제 사용할 때는 반드시 다운캐스팅을 해서 원래 타입으로 바꿔줘야한다.
부모 타입을 자식 타입으로 형변환 시키는 것
Car c1 = new Bmw();
//부모타입에서 정의되지 않은 자식타입의 메소드는 접근불가
c1.bmwNewFunction();
//다운캐스팅하여 다시 원래타입으로 변경
c1 = (Bmw)c1;
//이제 자기 타입으로 변경되었기 때문에 접근가능
c1.bmwNewFunction();
문법적으로 틀린 것은 아니지만 프로그램이 실행중에 발생할 수 있는 다양한 문제에 대한 처리를 하는 코드
예외를 방치하면 프로그램이 종료되는데, 이를 방지하기 위해 프로그램에 예외가 발생할 경우 이에 대한 처리를 해주어 프로그램이 계속해서 정상 동작할 수 있도록 한다.
가장 간단하게 예외처리를 할 수 있는 문법으로, try문 안에 예외가 발생할 것 같은 코드를, catch문 안에 예외 발생시 처리할 코드를 입력하여 프로그램을 동작하게 한다.
Integer num01 =10;
Integer num02 = 0;
Integer result;
//try catch는 모든 블록이 각각의 필드이기 때문에
//밖에 선언해야 안에서 쓸 수 있다. 안에서 선언하면
//해당 필드에서밖에 못씀
try {
result = num01 / num02;
//Exception은 최상위 예외이기 때문에 다 잡을 수 있지만
//다양한 예외 종류마다 처리가 달라야한다면
//Exception을 상속받는 예외 클래스별로 catch처리한다.
}catch (ArithmeticException e1){
//큰 범위로 예외를 처리하기 전에 디테일하게 처리
e1.printStackTrace();
result = 10;
} catch (Exception e2){
e2.printStackTrace();
result = 0;
}
//0으로 나누면 예외가 발생하지만 처리했기 때문에
//에러 로그는 찍히고 프로그램은 다음까지 정상동작한다.
//try catch를 쓸 때 변수가 초기화 되어있는지확인해야하고,
//해당 구문안에서 선언되지 않았는지도 확인해야한다.
System.out.println(result);
예외 처리를 바로 하지 않고, 해당 메소드를 호출한 곳으로 예외를 떠넘기는 키워드
해당 예외가 발생한 메소드를 최초 호출한 코드는 예외처리가 되어있어야 한다. (순수 Java 한정)
~와의 통로라는 의미
일반적으로는 H/W장치와의 통로라고 생각하면 편하다.
프로그램 기준으로 HDD에서 파일을 읽어오는 것이기 때문에 읽기 스트림: InputStream
저장은 HDD로 내보내는 것이기 때문에
저장 스트림: OutputStream이다.

스트림을 사용하면 반드시 다 쓰고 닫아줘야 한다.(열었을 때의 역순으로 닫아야 함)
입력 스트림 사용 예시
try {
//파일과의 통로를 열어서 바이트 단위로 데이터를 읽어오는 객체
FileInputStream fileInputStream = new FileInputStream("/Users/kangking/zzz.txt");
//글자 단위로 데이터를 읽어오는 스트림. 인코딩을 지정할 수 있다.
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"UTF-8");
//읽어온 내용을 담는다 (Buffer는 일종의 완충제 역할 - 속도가 빠름) 스캐너보다 빠름
BufferedReader br = new BufferedReader(inputStreamReader);
int res;
while ((res = br.read()) != -1){
System.out.print((char) res);
}
br.close();
inputStreamReader.close();
fileInputStream.close();
}catch (Exception e){
e.printStackTrace();
}
남의 컴퓨터에 실행중인 남의 프로그램과의 통로를 열어주는 스트림
OSI7레이어중 4계층까지 알아서 해주는 스트림
서버 소켓은 클라이언트의 요청을 대기하기 위한 장치로 생성자에 포트번호를 명시해주고, accept() 메소드를 사용하여 해당 포트로 클라이언트가 연결될 때 까지 대기한다.
//port번호를 생성자에 넘겨주어 해당 포트로 오는 요청에 대해 대기
serverSocket = new ServerSocket(9999);
//accept()로 대기하다가, 연결되면
//클라이언트 소켓의 정보를 담을 Socket 변수에 연결결과를 담아준다.
Socket clientSocket = serverSocket.accept();
소켓이 연결되면 소켓과 대상간 스트림이 개방되며 InputStream에 해당 스트림 연결을 빌려와 사용할 수 있다.
InputStream과 마찬가지로 OutputStream을 통해 연결된 스트림을 빌려와 사용할 수 있다.
즉, Socket으로 스트림을 개방하고, 해당 스트림에서 발생하는 Input과 Output을 InputStream, OutputStream으로 가져와 사용할 수 있다.