org.springframework.web.reactive.function.client.WebClientRequestException: readAddress(..) failed: Connection reset by peer; 오류 해결

 

현재 프론트엔드로 개발하고 있는데 간헐적으로 서버를 통해 외부 API를 요청할때 오류가 발생하는것을 확인 했다.

여기저기 찾아보니 

WebClinet를 사용해서 외부에 요청을 보낼때 대상서버의 연결이 닫혔을때 나타나는 오류 라고 한다. 

일단 의심이 가는 시나리오는

우리쪽 A서버에서 외부 B서버로 API 요청을 보내고 커넥션을 맺을때 B서버가 중간에 재실행 혹은

별도의 문제로 서버다운이 발생하는 경우라고 생각하여 해당 업체에 문의해본 결과

서버가 내려간적은 없다고 한다. 

 

두번째 시나리오는 B서버가 로드밸런서를 사용해 A서버에서 최초 요청시 B-1에 커넥션을 맺고 통신을 하다

다시 요청시에는 B-2 서버로 요청을 하는 경우

세번째는 로드밸런서 자체의 타임아웃이 A서버보다 빠른 경우

 

확인을 위해 해당 업체에 문의한결과 로드밸런서를 사용중이며 타임아웃이 10분이라고 한다.

 

오류 재현을 위해 테스트해보니 최초 요청 이후 10분후 재요청을 했을 경우에만 동일한 오류가 나는것을 확인하고

세번째 문제가 이유라고 판단 하였고 

다른분들이 작성한 깃이나 블로그의 도움을 받아 수정 할수 있도록 백엔드 팀에 전달하였다.

문제 해결을 위해 참고한 블로그및 사이트들이다.

참고 사이트

https://velog.io/@youngerjesus/Connection-Reset-by-Peer-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0

 

Connection Reset by Peer 문제 해결

Client 가 요청을 보냈는데 서버쪽에서 연결이 닫혔다고 다시 연결하라는 RST (Reset) 패킷을 보내는 경우에 이 에러가 발생한다.Connection prematurely closed BEFORE response 이렇게 쓰기도 한다. Client-Server 연

velog.io

https://jskim1991.medium.com/spring-boot-how-to-solve-webclient-connection-reset-by-peer-error-b1fa38e4106a

 

[Spring Boot] How to solve WebClient Connection reset by peer error

I had a requirement to fetch user data from an external system. It was implemented using WebClient as part of declarative http client…

jskim1991.medium.com

https://github.com/reactor/reactor-netty/issues/1774

 

Connection reset by peer exception · Issue #1774 · reactor/reactor-netty

We have a micro service based spring boot architecture where we are using spring webclient (which internally uses reactor netty) for internal communication between services. The issue that we faced...

github.com

 

 

해결방법

일단 해결 방법은 B서버 로드밸런서의 타임아웃시간에 도달하기 전에 우리쪽에서 먼저 연결을 해제하고

다시 커넥트를 거는것으로 해결 하였고 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Configuration
public class HttpProxyConfiguration {
 
    @Value("${tracker.url}")
    private String trackerUrl;
 
    @Bean
    TrackerClient trackerClient(WebClient.Builder builder) {
        ConnectionProvider provider = ConnectionProvider.builder("fixed")
                .maxConnections(500)
                .maxIdleTime(Duration.ofSeconds(20))
                .maxLifeTime(Duration.ofSeconds(60))
                .pendingAcquireTimeout(Duration.ofSeconds(60))
                .evictInBackground(Duration.ofSeconds(120)).build();
 
        HttpClient httpClient = HttpClient.create(provider);
        httpClient.warmup().block();
 
        var reactorClientHttpConnector = new ReactorClientHttpConnector(httpClient);
 
        var wc = builder.baseUrl(trackerUrl)
                .clientConnector(reactorClientHttpConnector)
                .build();
 
        var wca = WebClientAdapter.forClient(wc);
        return HttpServiceProxyFactory.builder()
                .clientAdapter(wca)
                .build()
                .createClient(TrackerClient.class);
    }
}
cs

 

이 코드를 참조하여 문제를 수정한것을 확인 할 수 있었고

위 코드의 각 부분의 설명을 보자면

  1. @Value("${tracker.url}"): 이 어노테이션은 tracker.url이라는 이름의 프로퍼티 값을 trackerUrl 변수에 주입(inject)합니다. 이 프로퍼티 값은 외부 트래커 서비스의 기본 URL을 포함하며, 애플리케이션 구성 파일(예: application.properties 또는 application.yml)에서 정의됩니다.
  2. TrackerClient trackerClient(WebClient.Builder builder) 메서드: 이 메서드는 TrackerClient 인터페이스의 구현체를 생성하고 구성합니다. 이 인터페이스는 외부 트래커 서비스와의 통신을 위한 메서드를 정의합니다.
  3. ConnectionProvider 설정: ConnectionProvider는 WebClient의 네트워크 연결을 관리하는 데 사용됩니다. 여기서는 최대 연결 수, 최대 유휴 시간, 연결의 최대 수명, 대기 중인 연결 획득 타임아웃 등을 설정합니다. 이 설정은 서비스와의 통신 중 발생할 수 있는 다양한 시나리오를 관리하기 위한 것입니다.
  4. HttpClient 생성 및 설정: HttpClient.create(provider)를 사용하여 ConnectionProvider를 사용하는 HttpClient 인스턴스를 생성합니다. httpClient.warmup().block() 호출은 HttpClient를 "온기"시키며, 네트워크 연결을 미리 설정하여 첫 번째 요청의 지연 시간을 줄이는 데 도움이 됩니다.
  5. WebClient 구성 및 생성: WebClient.Builder 인스턴스에 기본 URL, 클라이언트 커넥터 등을 설정하여 WebClient 인스턴스를 생성합니다. 이 WebClient 인스턴스는 TrackerClient의 HTTP 요청을 실행하는 데 사용됩니다.
  6. HttpServiceProxyFactory를 사용한 TrackerClient 생성: 마지막으로, HttpServiceProxyFactory와 WebClientAdapter를 사용하여 WebClient를 기반으로 하는 TrackerClient 인스턴스를 생성합니다. 이를 통해 외부 트래커 서비스와의 통신을 위한 프록시 클라이언트를 얻게 됩니다.

 

이렇게 정리될수 있으며 ConnectionProvider의 옵션은

  • builder("fixed"): 연결 풀의 이름을 "fixed"로 설정합니다. 이 이름은 로깅이나 디버깅 시 해당 연결 풀을 식별하는 데 사용될 수 있습니다.
  • maxConnections(500): 연결 풀이 동시에 유지할 수 있는 최대 연결 수를 500개로 설정합니다. 이는 애플리케이션이 동시에 열 수 있는 최대 연결 수를 의미하며, 이 한도를 초과하는 연결 요청은 대기 상태가 될 수 있습니다.
  • maxIdleTime(Duration.ofSeconds(20)): 연결이 유휴 상태(즉, 데이터를 전송하지 않는 상태)로 있을 수 있는 최대 시간을 20초로 설정합니다. 유휴 시간이 이 값을 초과하면 연결이 자동으로 종료됩니다.
  • maxLifeTime(Duration.ofSeconds(60)): 연결이 생성된 후 유지될 수 있는 최대 시간을 60초로 설정합니다. 이 시간이 지나면, 연결은 사용 여부에 관계없이 종료됩니다.
  • pendingAcquireTimeout(Duration.ofSeconds(60)): 연결을 획득하기 위해 대기하는 최대 시간을 60초로 설정합니다. 연결 풀에서 사용 가능한 연결을 얻기 위해 이 시간을 초과하여 대기하는 요청은 실패하게 됩니다.
  • evictInBackground(Duration.ofSeconds(120)): 비활성 연결을 정리하는 배경 작업의 실행 간격을 120초로 설정합니다. 이 설정은 연결 풀에서 오래되거나 더 이상 필요하지 않은 연결을 주기적으로 제거하는 데 사용됩니다.

위와 같다.

기존코드는 위의 옵션에 대한 별도의 설정이 없었기에 해당 오류가 발생하였었다.

 

VO에서 값을 가져오기 위해 vo.get이름() 이런식으로 가져오는데

getdata1 ~getdata32 이렇게 숫자증가단위로 여러개가 있는 경우

for문을 돌리면서 가져오고 싶을때가 있다.

vo를 for문으로 값을 가져오기 위해 자바 리플렉션을 사용했다.

저렇게 하면 메소드를 문자열로 바꿔서 불러올수가 있다.

 

map형식을 써도 되긴 하지만 애초에 vo형태를 잡아놓은것도 있고 다른데서 쓰고 있기 때문에

리플렉션의 비용이 조금더 들어가더라도 아래와 같은 방법을 사용 했다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    
        for(int count=1; count < 32; count++){
            
            String time = count+"";
            if(time.length()==1){
                time = "0"+count;
            }
            Class<?> c = vo.getClass();
            
            String value = null;
            try {
                Method method = c.getMethod("getT"+time);
                try {
                    value =  (String) method.invoke(vo);
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            HisDataVO updateVO = new HisDataVO();
        
            if(value.equals("")){
                value = null;
            }
            System.out.println(time+"회 :"+value);
            updateVO.setCOUNT(value);
            updateVO.setRECORD_DAY(vo.getRECORD_MON()+time);
            updateVO.setBUILDING_ID(vo.getBUILDING_ID());
            try {
                 result = goalSettingService.updateHead(updateVO);
            } catch (Exception e) {
                // TODO: handle exception
                System.out.println(e);
                System.out.println("업데이트 실패 "+time+"회");
                msg = "수정 실패 하였습니다";
            }
            
            
        }
        
cs

 

 

[JAVA] VO리스트에 add로 값 넣고 싶을때


프로젝트마다 다른 방식이겠지만


나는 주로


1
2
List<dataVO> result  = null;
result =  service.loadData(vo);
cs


이런식으로 가져 오는 방식을 선호한다


그런데


1
2
3
4
5
6
7
8
9
10
11
 
List<dataVO> result = null;
 
List<dataVO> data1 = null;
List<dataVO> data2 = null;
List<dataVO> data3 = null;
List<dataVO> data4 = null;
data1 =  service.loadData(vo1);
data2 =  service.loadData(vo2);
data3 =  service.loadData(vo3);
data4 =  service.loadData(vo4);
cs


각각의 데이터들을 result에 넣고자 하면


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
List<dataVO> result = null;
 
List<dataVO> data1 = null;
List<dataVO> data2 = null;
List<dataVO> data3 = null;
List<dataVO> data4 = null;
data1 =  service.loadData(vo1);
data2 =  service.loadData(vo2);
data3 =  service.loadData(vo3);
data4 =  service.loadData(vo4);
 
result.add(data1.get(0));
result.add(data2.get(0));
result.add(data3.get(0));
result.add(data4.get(0));
cs

이런식으로 넣으려 할텐데

저러면 에러가 난다


result가 null이기 때문이다


이때


result를


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
List<dataVO> result = new ArrayList();
 
List<dataVO> data1 = null;
List<dataVO> data2 = null;
List<dataVO> data3 = null;
List<dataVO> data4 = null;
data1 =  service.loadData(vo1);
data2 =  service.loadData(vo2);
data3 =  service.loadData(vo3);
data4 =  service.loadData(vo4);
 
result.add(data1.get(0));
result.add(data2.get(0));
result.add(data3.get(0));
result.add(data4.get(0));
cs



이렇게


new ArrayList(); 로 선언해주면


에러없이 값이 잘 들어간다.

[Java] 문자열 바이트로 자르기 


전문통신을 하다보니


한글의 경우는


바이트수가 바뀌어서 


난감했던 경우가 있다.


예를들어 300바이트 짜리 전문인데


영문과 숫자만 있으면 길이가 300이지만


한글이 섞여있으면


한글 1글자당 길이가 1개씩 줄어든다.


한글은 2바이트를 차지하기 때문인데


이때 바이트 단위로 끊어내고 다시 문자열로 반환해 주는 코드 이다.





public  String getString(String str, int sPoint, int length) throws Exception{
String EncodingLang = "euc-kr";
byte[] bytes = str.getBytes("euc-kr");

byte[] value = new byte[length];

if(bytes.length < sPoint + length){
throw new Exception("Length of bytes is less. length : " + bytes.length + " sPoint : " + sPoint + " length : " + length);
}

for(int i = 0; i < length; i++){
value[i] = bytes[sPoint + i];
}

/* System.out.println("utf-8 -> euc-kr : " + new String(word.getBytes("utf-8"), "euc-kr"));
System.out.println("utf-8 -> ksc5601 : " + new String(word.getBytes("utf-8"), "ksc5601"));
System.out.println("utf-8 -> x-windows-949 : " + new String(word.getBytes("utf-8"), "x-windows-949"));
System.out.println("utf-8 -> iso-8859-1 : " + new String(word.getBytes("utf-8"), "iso-8859-1"));
System.out.println("iso-8859-1 -> euc-kr : " + new String(word.getBytes("iso-8859-1"), "euc-kr"));
System.out.println("iso-8859-1 -> ksc5601 : " + new String(word.getBytes("iso-8859-1"), "ksc5601"));
System.out.println("iso-8859-1 -> x-windows-949 : " + new String(word.getBytes("iso-8859-1"), "x-windows-949"));
System.out.println("iso-8859-1 -> utf-8 : " + new String(word.getBytes("iso-8859-1"), "utf-8"));
System.out.println("euc-kr -> utf-8 : " + new String(word.getBytes("euc-kr"), "utf-8"));
System.out.println("euc-kr -> ksc5601 : " + new String(word.getBytes("euc-kr"), "ksc5601"));
System.out.println("euc-kr -> x-windows-949 : " + new String(word.getBytes("euc-kr"), "x-windows-949"));
System.out.println("euc-kr -> iso-8859-1 : " + new String(word.getBytes("euc-kr"), "iso-8859-1"));
System.out.println("ksc5601 -> euc-kr : " + new String(word.getBytes("ksc5601"), "euc-kr"));
System.out.println("ksc5601 -> utf-8 : " + new String(word.getBytes("ksc5601"), "utf-8"));
System.out.println("ksc5601 -> x-windows-949 : " + new String(word.getBytes("ksc5601"), "x-windows-949"));
System.out.println("ksc5601 -> iso-8859-1 : " + new String(word.getBytes("ksc5601"), "iso-8859-1"));
System.out.println("x-windows-949 -> euc-kr : " + new String(word.getBytes("x-windows-949"), "euc-kr"));
System.out.println("x-windows-949 -> utf-8 : " + new String(word.getBytes("x-windows-949"), "utf-8"));
System.out.println("x-windows-949 -> ksc5601 : " + new String(word.getBytes("x-windows-949"), "ksc5601"));
System.out.println("x-windows-949 -> iso-8859-1 : " + new String(word.getBytes("x-windows-949"), "iso-8859-1"));*/




return new String(value, EncodingLang).trim();
}


[톰캣] 서버 실행시 CMD창 바로 사라지는 문제 해결 방법






톰캣의 startup.bat 파일을 실행시킬때


cmd창이 떳다가 바로 사라지는 경우가 있었다.


뭐 에러 메세지라도 보여야 뭐가 잘못된건지 볼텐데


로그도 쌓이지 않고 그냥 사라져 버리는 문제에 대한 해결 방법이다.



일단 일반 cmd 창을 띄우고


톰캣이 설치된 경로로 이동한다



C:\apache-tomcat-7.0.76-windows-x64\apache-tomcat-7.0.76\bin



빈폴더 까지 이동 후


startup.bat  명령어를 입력하면


메세지가 나타나게 되는데


JRE_home environment variable is not defined correctly

a fatal exception has occurred. program will exit


요런 메세지가 나타난다.


JRE_home 가 아니라 JAVA_HOME 가 나타날 수도 있다


혹은 그외의 메세지가 나타날 수도 있으니


해당 메세지를 보고 오류를 해결하면 된다.


JRE_home environment variable is not defined correctly


이런 오류 메세지가 나타날떄의 해결 방법은


톰캣 bin 폴더의 catalina.bat 파일을 편집기로 열어서


JRE_HOME 나 JAVA_HOME의 경로를 


재지정 해주면 된다.



만약 JRE_HOME이나 JAVA_HOME 에 $JRE_HOME$ 이런 식으로


지정이 되어 있다면


시스템변수에 JAVA_HOME이나 JRE_HOME이 정상적으로


등록이 되어 있는지 확인 한다.



나의 경우는 JRE_HOME을 따로 지정하지 않았는데


톰캣 카탈리나에 JRE_HOME이 $JRE_HOME$ 으로 지정이 되어 있어서


시스템 변수에 JRE_HOME을 등록해 주고 난 후 오류를 해결 했다.



.




혹은 톰캣 윈도우를 실행 할때


지정된 서비스가 설치된 서비스로는 없습니다.


라는 메세지가 뜨는 경우


CMD창을 열어서


톰캣 빈폴더로 이동 후


service.bat install tomcat7


이라는 명령어를 입력하면


해결이 된다.







제어구조

:흐름을 제어

1.반복문

while(true)

{

break; ->무조건 벗어남.(선택적으로 벗어날 수 있도록 구성)

}

만약에 menu가 2라면 if (menu == 2) -->선택문




import java.util.Scanner;



public class forgugu {

public static void main(String[] args)

{

Scanner s = new Scanner(System.in);

System.out.print("1.숫자를 입력 하세요:");

int a = s.nextInt();

System.out.print("2.숫자를 입력 하세요:");

int b = s.nextInt();

System.out.println("입력한 값은:"+a+","+b);

if (a>b)

{

for (int i = b; i<=a; i++){

for(int j=1; j<10; j++)

{

System.out.println(i+"*"+j+"="+i*j);

}

}

}

else if (a<b)

{

for (int i=a; i<=b; i++){

for(int j=1; j<10; j++)

{

System.out.println(i+"*"+j+"="+i*j);

}

}

}

else

{

System.out.print("두 수는 같다");

}

}

}



선택 흐름(if문)

1.선택

2.검사 한번만

변수에서 유효한 범위->도메인

ex) 점수의 도메인 0~100

if(kor<0 || kor>100) 한번 검사!!!

여러번 검사 (while 문)


입력값을 검사 do while문




파일 입출력

FileOutputStream fos = new FileOutputStream(""


ctrl+shift+o =>자동으로 imprort

fos.write('A'); 문자하나하나만을 출력


FileOutputStream fos = new FileOutputStream("d:\\test.text");

fos.write('A'); //문자하나 쓰는 기능

fos.flush(); //비우는 기능

fos.close();


fos.flush();->데이터가 다 찰때까지 조금 기달리는 기능(끝에 한번만 선언)

while문 밖에다 선언


do{

c= fis.read();

if( c!= -1)


4bit=1byte


8bit


Big Endian   vs  Littile Endian

상속 - 기존에 있는 객체(부품)를 가져다 사용하기 위한 작업

* 재사용 - 컴파일된 바이너리를 다시 사용 // 소스 코드가 없는 상황에서 jar 파일을 import 시켜 사용

is a -


has a - 'a' 실존하는 객체를 부품(멤버)로써 가진다.

   상속되는 시점에 따라

     - composition has a - 내가 생성될 때 부품이 같이 생성된다.

     - association has a - 주입(인젝션)이 이뤄질때 생성된다.

                         - setter, constructor

     - aggregation has a - 1대 다로 has a 관계를 갖는다.



Is a 상속


<재사용을 극대화 하는 방법>

기존 재사용의 문제

-그대로 가져다가 사용

-만약 조금이라도 다르면 사용하지 못함


Is a 상속은 기존의 부품을 수정 또는 확장해서 사용 할 수 있는 방법이다.


- 클래스를 만들때 다음에 다시 사용 하기 좋도록(Is a 상속이 가능하도록) 만드는 것이 중요하다


frame work - 틀을 가져다가 고쳐 쓰는것




추상화 .

- 여러가지 사물이나 개념에서 “공통”되는 특성이나 속성 따위를 추출하여 파악하는 작용.- 네이버 사전

-공통분모를 만드는 과정



추상화한 클래스는 재사용을 위한 클래스.

단. has a 재사용이 불가능하다.(완전한 클래스가 아니기 때문에)

is a 재사용만 가능하다.


동일한 타입의 부품을 만들어야 할 경우에 추상화를 생각해 볼 수 있다.




-------------------------------------------------------┐

[비행기] <-        |

   △       |

       |

[적기] [아군기] [유람기]

동일한 행동을 한다.

--------------------------------------------------------



추상화된 클래스 또는 부모 클래스가 있을 경우 참조 방법에 모호함.



A a = new A();

A a = new B();

B b = new A(); <- 이건 안됨

B b = new B();


*재사용 되는 모든 부모*는 추상호된 클래스 *특징*을 갖는다.

왜냐하면 큰 범주에서 보면 공통분모가 되니깐

그렇다고 추상 클래스로 만들어진 것(집중화를 위해 만들어진 것)을 의미하지는 않는다.

단. 추상 클래스는 미완성 추상 클래스(집중화를 위해 만들어진 클래스)

와 완전 추상 클래스(기존의 재사용되는 클래스)로 나눌 수 있다.


기존의 클래스와 내가 부모자식 관계가 된다면 참조방법이 다양해 진다.


<- 구체화 클래스     추 상 클래스 ->

6강의장 학생 클래스, 학생 클래스, 사람 클래스 , 동물 클래스, 포유류 클래스, 생물 클래스


<필요한 클래스를 지목 =  만족하는 객체를 지목>

       사람 기선 = new 사람()

       6강의장학생 기선 = new 6강의장학생()

   사람 아무나 = new 6강의장핵생()

   사람 아무나 = new 7강의장학생()


문제

?? 기선 = new 6강의장학생()

위에서 6강의장학생 객체를 참조 할 수 있는 클래스의 개수는? (다 가능)


문제


동물 솔이 = new ??();

위의 식에서 솔이라는 이름으로 참조 할수 있는 개체의 종류는 총 몇개? (4개 동물,사람,학생,6강의장)



프로그래밍, 구조적 프로그래밍, 객체지향 프로그래밍.

재사용은 이미 만들어진것을 다시 사용 하는 것(소스 코드 재사용X)


객체지향 - 캡슐화 -> 상속 -> 다형성




다형성->추상화



오버 라이드! 한것 우선으로 호출된다



정적 바인딩, 동적 바인딩


자바는 동적 바인딩을 사용한다.


객체가 전달 되면서 함수목록을 제출???


객체들은 자기 주소를 가지고 간다.





다형성 - 다양한 용도로 써먹을 수 있는 성질

어떤 클래스를 다양하게 써먹을 수 있도록 작성할 수 있는 능력을 갖는데 있다.



인터페이스





행위는 같지만 근본이 다른놈?


참조는 공간만 참조.

String 클래스(모든 클래스는 object이다.)


자바는 완전한 객체지향이다.

(Boxing과 UnBoxing)


Integer x = 3; => Integer x = new Integer(3);

일케 쓰면      컴파일러가   일케 만들어준다.


값을 참조할수 있도록 박싱(뤱(wrap)픵 yoyo )

요즘은 오브젝트에 그냥 값만 넣어도 알아서 만들어줌 ( 오토 빡싱)


Object x= 3;   => Object x = new Integer(3);

int y = x;(초창기엔 에러가 났는데 요즘은 안난다 오토 언빡싱)


Object x= 3;   => Object x = new Integer(3);

add(x,4);  x 에 참조가 아닌 값이 전달됨.

Boxing에 사용되는 Wrapper 클래스


Object ──── ① Number : Byte, Short, Long,Integer등등

                      ② String


int a = 3.intValue(); ---> 앙대요  < 요게 안대거

new Integer(3).intValue();---->되요

객체로 만들어줘서 나오는거        that’s yes yes ㅎㅇ

int b = “hello”.length(); -->되요


String 객체의 ‘+ (덧셈)‘ 은 미리 연산자 오버로딩이 된 메소드이다.


제어 구조

- 흐름(절차)을 제어하는 것

선택문 > 반복문 > 분기문


선택문 : if-else - 배타적인 관계로(검사 할 때 많이 사용함) (유효한 값의 범위 : 도메인)

반복문 : while - 조건이 거짓이 될 때까지 반복 (반복 검사)

for - 원하는 만큼의 반복

분기문 : 많은 선택지(비교)를 갖게 되는 선택문 (else-if)의 단점 때문에 분기문을 사용.


파일 입출력

* 콘솔을 이용한 입출력은 객체가 이미 지정되어있지만 파일 입출력은 stream 객체를 지정해 주어야한다.

FileOutputStream fos = new FileOutputStream(“d:\\test.txt”);  // import + 예외처리

fos.write(‘A’);

fos.flush();

fos.close();

* 버퍼는 약 8kb의 크기를 가지고 있다.


배열

입력 -> 데이터 -> 출력의 과정에서 저장소의 필요성이 생김

장점 : 일괄적으로 데이터를 처리할 수 있다. (반복문 사용)


FileInputStream.read(public int read(byte[] b, int off, int len) --> off부터 시작해서 ‘len’바이트를 읽는다.



역참조 연산?



모듈화



스택


동적 할당 - heap 영역


static

인스턴스메소드 (스태틱X) - 객체명을 통해 호출 된다.



캡슐화 - 데이터구조/함수를 묶어놓는것

왜? 캡슐화 된 데이터/함수에 구조가 바뀌게 되었을때 유지보수를 편하게 하기 위해.

캡슐이 실체화되면 객체.


생성자 - 객체가 생성될 때 가장 먼저 실행됨, 입력 O 출력 X

데이터를 초기화 하기 위함 (클래스이름과 동일한 함수명 사용, 반환타입 X)


오버로딩 - 함수명이 중복되었을때

인자가 없는 쪽이 기본, 인자가 있는 쪽이 중복된다고 본다.

this 키워드 -- 오버로딩이 된 함수가 있을 때 this() 키워드를 통해 인자를 전달하여 다른 오버로딩된 메소드를 호출 할 수 있다.

연산자 정리…



코딩을 하면서 여러가지 복합적인 연산을 해야 하는 경우가 있을때 기본적으로 알고 있어야 할 사항 들이다


외우지 못해도 좋다 연산자의 연산 우선순위라는게 존재한다는 것만 알아두면 필요할때 검색하거나 이렇게 찾아서


사용하면 되니까.



문자열 입력


1.숫자 입력

출력 코드 위에다가 각 숫자를 입력하는 코드가 필요

(입력을 하기 위해선 출력문이 필요)

입력버퍼(System.in 입출력은 너무 자주사용하여 정의 해놓았다.)

System.in = new ConsoleInputStream();

int key = System.in.read();

입력을 하기 위해선 입력 버펴에 하나씩 쌓이게 된다.

엔터를 만날때 까지 자료형을 변환해주는 메소드가 존재

next()

nextLine()->하나의 줄을 받아서 변환

nextInt()->스페이스 전까지의 숫자를 변환  >

ex)”30 40 50”을 입력시 30 하나만을 가져오고 버퍼에는 “40 50”이 남아있게 된다.

nextfloat()

Scanner = 문자를 입력할 수 있게 하는 도구 ex)핸드폰

new = 개체화

Scanner scan = 도구는 이름을 붙여 주어야 한다

System.in = 입력 버퍼에 값 전달/종속 객체 ex)배터리

  (배터리를 핸드폰에 주입한다.->즉 System.in을 Scanner에 주입한다.)


Scanner : 입력 버퍼에서 값을 스캔하는 것 ex) Scanner scan = new Scanner(System.in);

+ Recent posts