httpClient는 아파치 재단에서 URL 클래스를 훨씬 좋게 만든 것 (HTTP 프로토콜로 요청/ 응답 수행 가능)
안드로이드 OS에도 표준탑재되어 서버에서 정보를 다운받는 용도로 사용한다.
public class Test127{
public static void main(String[] args) throws IOException{
//CloseableHttpCilent : 실제로 요청 / 응답을 수행하는 핵심
CloseableHttpClient httpClient = HttpClients.createDefault();
String l = "http://192.168.2.11:8081/study3/Test126.jsp?pw=1234";
HttpGet httpGet = new HttpGet(l); //get 방식요청
httpGet.addHeader("User-Agent", "Mozila/5.0"); //헤더 조작 여지
// execute 실제로 요청/응답을 수행한다. httpResponse가 응답이다
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
int resCode = httpResponse.getStatusLine().getStatusCode();
if(resCode == 200) {
InputStream in = httpResponse.getEntity().getContent();
BufferedReader bin = new BufferedReader(new InputStreamReader(in));
// new InputStremReader(in, "utf-8") 한글 깨지면 이거 써라...
BufferedReader bin = new BufferedReader(new InputStreamReader(in));
// new InputStremReader(in, "utf-8") 한글 깨지면 이거 써라… **
// why? => java default unicode / web default utf-8
String str = null;
while((str=bin.readLine())!=null){
System.out.println(str);
}
}
}
}
우리는 지금 Get 방식으로 사용하는 법을 배웠다. 많은 정보를 서버에서 다운받는 것에는 차이가 없다 GET이 든 POST든 Client에서 대량의 정보를 업로드 하려면 POST를 써야함 ** 위 코드와 많이 틀려지게 되니 이 점 유의할것 BufferedReader bin = new BufferedReader(new InputStreamReader(in)); ** new InputStremReader(in, "utf-8") 한글 깨지면 이거 써라… **
commons-logging.jar log4j-1.2.17.jar 은 lib 폴더에 넣는다.
%m%n 만 해도 됨ㅎㅎ [시간] INFO about : HelloWorld 이런 식으로 뜸
로그 파일의 형식 지정 : 단순히 콘솔에 찍어보는 걸 넘어서 내부적인 동작을 고스란히 담아낼 수 있다.
로그파일 분석 툴을 이용하면 사이트 전반의 분석을 가능하게 한다.
3. 실전에는 Util.L(…) 같은 거 만들어서 쓰는 경우가 많다.
pageNavigation
페이지 개수 = ((글 갯수 -1) / 페이지 크기 ) + 1
블럭 사이즈 (BS) : 10 단위로 하단에 보여짐
이전 페이지 : (BB!=1)
다음 페이지 : (BE != 총 페이지 수)
BB = ((CP -1)/ 10) * 10 +1 : 처음 보여줄 1 2 3 4 5 개 / CP 는 1 2 3 4 5 .. 들 중 하나
1. 정렬된 순서 보기
SELECT id, title FROM Temp10T ORDER BY id DESC;
2. rownum??
SELECT id, rownum FROM Temp10T;
SELECT id, rownum FROM Temp10T ORDER BY id DESC;
—row num은 order by 이전에 부여된다. 따라서 order by 이후에 rownum으로 쪼개는 건 무의미
— 그러면 orderby 시켜놓고 그 다음에 rownum 붙이겠다?
SELECT id, rownum FROM ( SELECT id FROM Temp10T ORDER BY id DESC );
3. rownum을 기준으로 페이지 나누기?
SELECT id, rownum FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) WHERE rownum > 0 AND rownum <= 5;
SELECT id, rownum FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) WHERE rownum > 5 AND rownum <= 10;
Rownum 이 10까지 없고 모자란다? 5개 가져오는 중에 5~10 사이가 없음 안됨
4. rownum을 field로 굳혀놓고 나누기!!
SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC );
SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) ) WHERE sq > 0 AND sq <= 5; SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) ) WHERE sq > 5 AND sq <= 10;
5. 서브쿼리로 정리해서 깔끔하게!!
SELECT * FROM Temp10T WHERE id IN ( SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T ORDER BY id DESC ) ) WHERE sq > 10 AND sq <= 20 ) ORDER BY id DESC;
select * from (select id, rownum as sq from (select id from temp10t where 0=0 order by id desc))
where sq>20 and sq<=30;
6. 나중의 검색을 위해서 0 = 0 은 그냥 끼워 넣어준다(검색을 어떻게 할지 생각해 보자)
SELECT * FROM Temp10T WHERE id IN ( SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T WHERE 0 = 0 ORDER BY id DESC ) ) WHERE sq > 5 AND sq <= 10 ) ORDER BY id DESC;
여기에서 0 = 0 을 응용하여 검색기능에서의 나누기 시도한다.
StringBuffer find = new StringBuffer(" WHERE 0 = 0"); if( title != null ){ find.append(" AND title LIKE '%"); find.append( title ); find.append("%'"); } if( user != null ){ find.append(" AND user ='"); find.append( title ); find.append("'"); } if( content != null ){ find.append(" AND content LIKE '%"); find.append( content ); find.append("%'"); }
String subSql = "SELECT id FROM " + "( SELECT id, rownum as sq FROM " + "( SELECT id FROM Temp10T "+ find.toString() + " ORDER BY id DESC ) )" + "WHERE sq > 5 AND sq <= 10";
String countSql = "SELECT COUNT(*) FROM Temp10T " + find.toString(); String sql = "SELECT * FROM ("+ subSql +") ORDER BY id DESC";
그러면 아래와 같은 형태의 결과를 보게 될 것이다.
SELECT COUNT(*) FROM Temp10T WHERE 0 = 0 AND user = 'root' AND content LIKE '%ab%'
....
SELECT * FROM Temp10T WHERE id IN ( SELECT id FROM ( SELECT id, rownum as sq FROM ( SELECT id FROM Temp10T WHERE 0 = 0 AND user = 'root' AND content LIKE '%ab%' ORDER BY id DESC ) ) WHERE sq > 0 AND sq <= 3 ) ORDER BY id DESC;
0=0 위치가 검색 조건이 들어갈 위치
select * from temp10t where id in(select id from (select id, rownum sq from (select id from temp10t where title like '%bc%' order by id desc))where sq>0 and sq<=10) order by id desc;
Mysql
create table Temp10t(
-> id integer(3),
-> title varchar(7));
~insert로 입력
select * from temp10t order by id desc limit 0, 10;
10 씩 쪼개줌
select * from temp10t order by id desc limit 10, 10;
10개 세고 또 10개
> form-group으로 지정된 div를 이용하여 label과 input을 한쌍으로 묶어서 보여준다
함수의 매개변수의 갯수가 틀려도 호출된다. 만일 갯수가 틀리면 앞의 변수부터 대입이 된다.
변수 선언시에는 var라는 키워드를 사용한다. 변수는 모든 값이 대입 가능 (정수, 문자열, 실수, 함수, 객체...)
두번 선언해도 에러 안나고, var없이 선언해도 에러 안난다
script 태그 안에 있는 코드는 페이지가 모두 로딩 되지 않은 상태에서 호출 변수를 선언하지 않고 사용하면 초기값은 undefined이고 여난이 불가능하다.
var total=0; 코드가 빠졌을 때 에러가 나는 이유를 점검하자.
java는 블럭 안에서 선언한 변수는 블럭에서만 쓸 수 있는 개념인데 javascript는 선언만 되어 있으면 쓸 수 있고, 선언 안해도 쓴다
모든 html 요소는 id 속성을 가질 수 있다
속성 값은 pk처럼 겹치면 안된다
Document.getElementById("abcd") : id 값으로 객체의 포인터를 찾는다
window.onload = function(){
var op = document.getElementById("abcd");
op.onclick = function () {
alert();
}
}
/*op라는 포인터 변수로 해당 객체를 가리킨다
포인터를 통해 객체가 가진 속성을 읽고, 조작할 수 있다
op.onclick은 op 포인터가 가리키는 객체의 onclick 이라는 변수(프로퍼티)
javascript 변수는 다 가리킬 수 있다.
onclick은 이름없는 함수와 다름 없다.
가리키는 것과 호출하는 것은 다르다(여기서는 가리키기만 한다.)
호출되는 시점?
op 가리키는 객체에 click 상황이 벌어지면 onclick 이 가리키는 함수가 호출된다.
이벤트 처리의 두가지 방법
1. onXXX 속성을 이용하는 방법 : onclick="alert();"
2. onXXX 속성을 함수포인터로 쓰는 방법 : 위 코드의 방법.(이 방법이 더 많이 스임).*/
window.onload = function(){
var is = document.getElementsByTagName("img");
for(var i=0;i<is.length;i++){
alert(is[i].src);
}
}
/*ls[0] = function(){alter(i)} 가리키는 시점에서는 i가 0인데, 호출하는 시점에서는 4가 된다
가리키는 시점의 값과 호출하는 시점의 값이 같아야 한다
=> 함수의 매개변수를 활용한 로컬변수를 사용해야한다*/
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Controller {
public String handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception;
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
public String value();
}
package mvc;
//import 생략~
public class DispatcherServlet extends HttpServlet {
private Map<String, Controller> map = null;
@Override
public void init(ServletConfig config) throws ServletException{
map = new Hashtable<String, Controller>();
String cs = "mvc.CtrlList,mvc.CtrlAdd2";
for(String str : cs.split(",")){
try{
//해당 클래스 가져오고
Class<?> cls = Class.forName(str);
//RequestMapping에서 지정된 url 패턴 따오고
RequestMapping an = cls.getAnnotation(RequestMapping.class);
//얘 때문에 Controller에너는 Annotation!
System.out.println("this is an : " + an);
//해당 controller instance 받아오고
Controller value = (Controller) cls.newInstance();
// 이름이 str인 Controller 클래스 찾기
// url 따기
String key = an.value();
//url-pattern과 controller 매핑
map.put(key, value);
}catch (Exception e) {}
} //String[] cs2 = cs.split(","); for(int i=0;i<cs2.length;i++)
System.out.println(map.toString());
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse
response)
throws IOException, ServletException {
}
}
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RequestMapping("/apple_list.do")
public class CtrlList implements Controller {
@Override
public String handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return null;
}
package mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RequestMapping("/apple_add2.do")
public class CtrlAdd2 implements Controller{
@Override
public String handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
return null;
}
}
JSP MODEL1 / MVC MODEL2
<model1>
가장먼저 들어오는 곳이 JSP이다.
JSP에서 비즈니스 로직, VIEW모든 것을 처리한다.
<model2>
가장먼저 요청하는 곳이 서브릿단이다.
비즈니스 로직을 처리하는 서블릿을 완전히 분리시켜서 VIEW단과 로직을 처리하는 단을 분리시킨다.
Controller 추가해야할 때
<servlet>
<servlet-name>abcd2</servlet-name>
<servlet-class>mvc.DispatcherServlet</servlet-class>
<init-param>
<param-name>controllers</param-name>
<param-value>
mvc.CtrlList,
mvc.CtrlAdd2
</param-value>
</init-param>
</servlet>
<!-- 여기 이렇게 controller를 추가하면 되지 않을까! -->
public void init(ServletConfig config) throws ServletException{
map = new Hashtable<String, Controller>();
String cs = config.getInitParameter("controllers");
HTML 소스 긁어오는애
package main;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
public class Test126 {
public static void main(String[] args) throws Exception{
URL rl = new URL("http://localhost:8081/0802/apple_list.do");
URLConnection ucon = rl.openConnection();
InputStream in = ucon.getInputStream();
BufferedReader bin = new BufferedReader(new InputStreamReader(in,
"UTF-8")); //>> char 단위로 읽게해주는 adapter
//사실 UTF-8 빼도 되더라 얜 응답 내용
String l = null;
while((l = bin.readLine()) !=null){
System.out.println(l);
}
in.close();
}
}
java.net.URL은 이것 자체가 작은 웹브라우저의 역할을 한다. 요청을 날리고 그에 해당하는 응답을 받아들인 다 안드로이드 앱에서 버튼을 누르면 오늘의 배송정보가 넘어오는 ? 배송정보는 서버에 올라와 있는 상태! => 이 다운 받는 역할, 서버에 존재하는 배송정보를 다운받는 역할을 수행한다. 소켓으로 다 짜는 것이 아니라 http 프 로토콜로 서버와 통신할 때는 이 클래스를 주로 이용한다. 소켓으로 다 짜는 것이 아니라 http 프로토콜로 서버와 통신할 때는 이 클래스를 주로 이용한다. 앱 같은 경우에서 서버로부터 많은 데이터를 다운 받아야 할 경우에 URL 클래스를 이용하여 jsp 파일로부터 정 보를 다운받는다 이게 워낙 많이 쓰이다 보니 이를 강화한 오픈 소스 라이브러리가 등장 = apache http client 프로젝트 = 안 드로이드의 http 기반 표준 통신 수단
암호가 맞으면 다운, 아니면 안됨
<%@ page contentType="text/plain; charset=UTF-8" pageEncoding="EUC-KR" %><%
String pw = request.getParameter("pw");
if(pw.equals("1234")){
String[] l = {"사과", "귤", "배", "토마토"};
String nl = "\r\n"; //줄 바꿈 표시
for (int i = 0; i < l.length; i++) {%>
<%=l[i]%><%=nl%>
<%}}else{%>
암호틀림
<%}%>
public static void main(String[] args) throws Exception{
URL rl = new URL("http://localhost:8081/0802/Test126.jsp?pw=1230");
URLConnection ucon = rl.openConnection();
InputStream in = ucon.getInputStream();
BufferedReader bin = new BufferedReader(new InputStreamReader(in, "UTF8")); //>> char 단위로 읽게해주는 adapter
//사실 UTF-8 빼도 되더라 얜 응답 내용
String l = null;
while((l = bin.readLine()) !=null){
System.out.println(l);
}
in.close();
}
SQL> create table temp20t( 2 data char(3) null 3 );
테이블이 생성되었습니다.
SQL> insert into temp20t values('abc');
1 개의 행이 만들어졌습니다.
SQL> insert into temp20t values(null);
1 개의 행이 만들어졌습니다.
Q. NULL 4글자가 입력 가능? null은 빈값을 의미
insert into temp20t values('null'); -> null과 'null'은 구분하자
% select * from temp20t where data = null; NO
select * from temp20t where data is null; YES
(null 과의 비교는 is를 이용한다)
<문제점>
package main;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class Test110 {
public static void main(String[] args) throws Exception {
String data = "xyz";
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
//sql 이어 붙일 땐 ''에 주의해야한다
//data에 null 일 때는 에러 -> 왜? null이라는 문자열이 들어가는 것으로 됨
//나름 해결책 이지만 null 가능 필드가 2개면 경우의 수가 4개 / 3개면 8개
//이런 문제 떄문에 현업에서는 PreparedStatement를 더 선호한다.
//현업에서는 아예 char 는 무조건 4자리 이상을 잡게 하는 경우도 있다.
String sql =(data != null) ?
"insert into temp20t values ('"+data+"')":
"insert into temp20t values(null)";
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);
stmt.close();
conn.close();
}
}
<해결책>
package main;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test111 {
public static void main(String[] args) throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
/*Statement 가 어떤 sql 문장이든 실행하는 범용적인데 반해서
* preparedStatement 는 생성시에 준비한 그 문장만 실행 할 수 있다
* 대신 ? 영역을 setString , setInteger등을 이용하여 채울 수 있다
* (순서가 1부터 시작하는 것에 주의)
* execute 시에 매개변수 없음에 주의*/
String sql = "insert into temp20t values(?)";
PreparedStatement stmt = conn.prepareStatement(sql); //sql문장 전용의 바구니
// stmt.setString(1,"LEE");
stmt.setString(1, null);//에러 안남 null값이 들어간 행이 생김
//이걸 쓰면 null 값을 넣을 때 ''를 붙여야 할지를 결정하기 위해 이런저런 고민 할 필요가 없어진다(위의 코드처럼)
stmt.executeUpdate();
stmt.close();
conn.close();
}
}
/*SQL> select * from temp20t;
DATA
------
abc
xyz
xyz
xyz
LEE -> 컴파일 시 들어감*/
AUTOBOXING / UNBOXING
package main;
public class Test112 {
//매개변수로 String 을 0..*개를 넣어도 에러가 안나는 선언 방식
public static void test2(Object...args){
for(int i = 0; i < args.length; i++){
if(args[i] == null){
System.out.println("null");
}else if(args[i] instanceof Integer){
int r = ((Integer)args[i]).intValue();
System.out.println("null");
}else if(args[i] instanceof Double){
double r = ((Double)args[i]).doubleValue();
System.out.println(r+0.1);
}else if(args[i] instanceof String){
System.out.println((String)args[i]);
}
}
}
public static void test(String... args){
System.out.println(args.length);
}
//Object arg_1 = 100; -> 100을 new Integer(100)로 자동변환
//Object arg_3 = 3.14; => 3.14를 new Double(3.14)로 자동변환
public static void main(String[] args){
test2(100, "Hello", 3.14, null);
test("apple");
test();
test("apple", "banana");
}
}
/*autoboxing unboxing
*
* Object i = 100;(o)
* int i = j;(x)
*
* Integer i = 100(o)
* int j = i;(o)*/
<프레임워크 만들기>
package main;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test113 {
public static int update(String sql, Object... args) throws Exception{
int rc = 0;
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@127.0.0.1:1521/XE","HR","HR");
PreparedStatement stmt = conn.prepareStatement(sql); //sql문장 전용의 바구니
for(int i = 0; i < args.length; i++){
if(args[i] == null){
stmt.setObject(i+1, null);
}else if(args[i] instanceof Integer){
int r = ((Integer)args[i]).intValue();
stmt.setInt(i+1, r);
}else if(args[i] instanceof Double){
double r = ((Double)args[i]).doubleValue();
stmt.setDouble(i+1, r);
}else if(args[i] instanceof String){
stmt.setString(i+1, (String)args[i]);
}
}
rc = stmt.executeUpdate();
stmt.close();
conn.close();
return rc;
}
public static void main(String[] args) throws Exception{
String sql = "insert into temp20t values(?,?)";
update(sql, "KIM",100);
}
}
/*프레임워크 만들기 */
<Anonymous class>
package main;
interface ITemp{
public void print();//인스턴스 못만듬 , abstract 클래스이기 떄문에
//클래스 : 참조형변수 선언/ 인스턴스 생성 / 상속해서 인스턴스 선언
}
public class Test114 {
public static void main(String[] args){
/*Anonymous class : 이름 없는 클래스
* -> 조상은 있음 : ITemp
* ITemp를 상속받고 -> 모든 메소드 오버라이딩 해주고
* 이름이 없어서 재사용은 불가능하다
* -클래스 선언하고 , 인스턴스 생성하고는 끝
* t가 왜 가리킬 수 있는 거지? A t = new B() 자손이 조상에서 오버라이딩한 것을 가져올 수 있기 때문에 */
final int i = 100; //i = 로컬변수다 -> final로 선언해주면 어나니머스 클래스에서 사용할 수 있음 / 객체 지향 개념
ITemp t = new ITemp(){
public void print(){
System.out.println("HelloWorld" + i);
}
};
t.print();//자손 인스턴스가 소환
}
}
JSP 기본 문법
JSP 페이지
<%-- JSP 주석 --%>
<% 스클립틀릿(자바 명령문) %> -> 웹 서버 쪽 실행
<%= 익스프레션 %> -> 자바식 (연산자 포함식, 메서드 호출식) -> 웹 서버 쪽 실행 => 웹 브라우저로 실행
${ 익스프레션 랭귀지 } - 빠른 간단한 연산 가능
<HTML>
<BODY>
<% int total = 0;
for(int cnt = 0; cnt <= 100; cnt++)
total += cnt;
%> //스클립틀릿 -> 자바 명령문
<%= total %> //익스프레션 -> 자바식(연산자 포함식, 메서드 호출식)
</BODY>
</HTML>
서블릿 클래스
서블릿 클래스 골격 선언 -> service 함수 메서드 선언 -> 명령 -> 파일로 텍스트 출력
//서블릿 클래스 골격 선언
public class Servlet extends HttpServlet{
//service 함수 메서드 선언
public void service(HttpServletRequest request, HttpServletResponse response)
throws IOException ServletException{
//명령
for(int cnt = 1; cnt <= 100; cnt++)
total += cnt;
//파일로 텍스트 출력
PrintWriter out = response.getWriter();
out.println("<HTML>");
out.println("<BODY>");
out.println("%d",total);
out.println("</BODY>");
out.println("</HTML>");
}
}
<web.xml> 에 서블릿 등록
<servlet>
<servlet-name>Servlet-test</servlet-name>
<servlet-class>servlet</servlet-class>
</servlet> //서블릿 클래스 이름이 들어감
<servlet-mapping>
<servlet-name>servlet-test</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping> //서블릿 클래스 호출할 때 사용할 URL 들어감
<쿠키 : 웹 브라우저 쪽에서 데이터 입력, 수정, 삭제, 조회 >
-> 결제 모듈에서 사용 / A, B, C 서블릿이 각자 있고 각자의 유저가 쿠키를 생성하여 따로 저장할 수 있음 (장바구니 , 로그인 정보에 사용)
package study3;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*http://localhost:8081/study3/state?use=readCookie
* 요청 -> 응답, 요청의 방법이 두가지 get / post // get : 엽서 / post : 택배
*
* 엽서와 주소의 내용을 구분하는 선의 역할 : ?
* ? 오른쪽 내용 : key=value 형태로 구성
* request.getParameter를 이용하여 추출할 수 있따
* 거의 대부분이 get방식이고 form 에서 method = "POST"로 지정된 경우만 POST방식*/
public class StateServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String use = request.getParameter("use");
if("addCookie".equals(use)){
Cookie ck = new Cookie("name", "apple");
response.addCookie(ck);
}else if("readCookie".equals(use)){
Cookie[] cks = request.getCookies();
if(cks != null){
for(int i = 0; i < cks.length; i++){
String l = cks[i].getName() + ","+ cks[i].getValue();
System.out.println(l);
}
}else{
System.out.println("Cookie is null");
}
}
System.out.println(use);
}
//addcookie 후 read 쿠키를 하니
/*Cookie is null
readCookie
getCookie
/*쿠키는 서블렛과 다르게 브라우저에서 생성 -> 서버에서 알 수 있는 방법은 응답이 넘어갈 때(addCookie -> response 멤버 변수)
*요청할 때 쿠키를 물고온다 / 응답 내보낼때만 서블릿이 조작할 수 있음
*/
}
세션사용
최초 getSession() 호출시에는 고유 넘버가 없이 요청이 들어온다 * 기억장소 생성 - Map<String, Object> 형태 * 고유 넘버 생성 * JSESSIONID 키 값으로 고유 넘버를 쿠키에 저장 * * 그 이후에 getSession() 호출 : 고유 넘버 물고 왔으니 그걸로 기억장소 찾는다 * "브라우저 마다 개별적인 기억장소가 생성된다"
package study3;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
//session으로 접근 가능하게 만드세요
// http://localhost:8081/study3/state?use=readCookie
public class SessionServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
System.out.println( session.isNew() );
//true
//JSESSIONID,2C7E8E0D95817C0E56780B2B4644924D
session.setAttribute("apple", "Object!!");
Object value = session.getAttribute("apple");
System.out.println(value.toString());
/*false
Object!!
*/
/*최초 getSession() 호출시에는 고유 넘버가 없이 요청이 들어온다
* 기억장소 생성 - Map<String, Object> 형태
* 고유 넘버 생성
* JSESSIONID 키 값으로 고유 넘버를 쿠키에 저장
*
* 그 이후에 getSession() 호출 : 고유 넘버 물고 왔으니 그걸로 기억장소 찾는다
*
* "브라우저 마다 개별적인 기억장소가 생성된다"*/
}
}
<jsp>
<%@ page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%> <%! int i = 0; %> <% int j = 0; %> http://www.w3.org/TR/html4/loose.dtd">
<%=i++ %> <%=j++ %>
<%-- jsp 주석 ,html 파일 요청하듯이 요청한다(web.xml 수정할 필요 없다) i = 멤버 변수 / j = 로컬 변수의 느낌이 난다 jsp 파일을 요청하면 톰캣은 이것을 *.java 파일로 변환한다(서블릿코드) 이것은 컴파일하고 인스턴스를 만들어 적재하고 인스턴스 재활용 한다
서블릿 이후에 asp의 등장으로 위기를 느낀 자바쪽에서 ASP 비슷하게 만든 게 JSP http://192.168.2.11:8081/study/Test115.jsp --%>
package study3;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class JSPServlet extends HttpServlet{
private ServletContext application = null;
//대표적인 함수 getRealPath
private ServletConfig config = null;
//적재된 서블릿의 시점을 가져오는 것이 init 함수
@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
application = config.getServletContext();
}
/*--------------------------------------------------------------------------------
*<%! ... %> 은 여기에 온다
* int i = 0;
*-------------------------------------------------------------------*/
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
PrintWriter out = response.getWriter();
/*--------------------------------------------------
* <%....%>은 여기에 온다
* int j = 0;
* --------------------------------------------------*/
/*--------------------------------------------------
* <%=... %은 print()로 감싸서 나온다
* <%=i++ %>
* out.println(i++);
<%=j++ %>
out.println(j++);
Test115.jsp > 유사한 형태로 변환되고 컴파일되고 인스턴스 만들어지고 적재된 뒤에 실행한다
* --------------------------------------------------*/
out.flush();
out.close();
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<body>
<!-- input type = "file" : 파일을 서버로 업로드 할 때 사용
이때 반드시 enctype = "multipart/form-data" 을 사용한다
fileup 에 해당하는 서블릿은 cos.jar 파일의 MultipartRequest 를 이용하여 업로드를 처리하는 것이 일반적
-->
<form method = "POST" action = "fileup" enctype = "multipart/form-data">
<input type = "text" name = "title" size = "20">
<input type = "file" name = "apple">
<input type = "submit">
</form>
</body>
</html>
<fileUpServlet.jsp>
package study3;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;
import java.io.InputStream;
public class FileUpServlet extends HttpServlet{
private ServletContext application = null;
@Override
public void init(ServletConfig config) throws ServletException {
application = config.getServletContext();
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String l = process2(request);
System.out.println(l);
}
/*request : 요청 , 브라우저에서 서버로 전달하는 개념
* request.getInputStream() 은 브라우저에서 서버로 전달되는 내용을 볼 수 있다
* 이 내용을 재구성하는 기능이 cos.jar 파일의 MultipartRequest 이다.
* .*/
public String process(HttpServletRequest request) throws IOException{
byte[] buf = new byte[1024];
int len = 0;
StringBuffer sb = new StringBuffer();
InputStream in = request.getInputStream();
while((len = in.read(buf)) != -1){
sb.append(new String(buf, 0, len));
}
in.close();
return sb.toString();
}
public String process2(HttpServletRequest request) throws IOException{
//fileup 디렉터리의 실제 저장 위치(절대 경로) 값을 파악한다.
String path = application.getRealPath("/WEB-INF/fileup");
System.out.println(path);
//cos.jar에서 제공되는 클래스
//DefaultFileRenamePolicy : 이름이 겹칠 때 이름 바꿔서 올린다
//따라서 올릴 때 이름과 서버에 올려진 이름이 다를 수 있따.
MultipartRequest mpr = new MultipartRequest(
request, path, 1024*1024*20, "UTF-8",
new DefaultFileRenamePolicy());
//업로드한 원래 파일이름
String ofn = mpr.getOriginalFileName("apple");
//중첩될 경우 이름을 바꾸어 저장하는 이름
String fsn = mpr.getFilesystemName("apple");
System.out.println(ofn +","+ fsn);
//MultipartRequest 쓰면 request.getParameter 못쓴다.
// 대신 MultipartRequest 안의 getParameter 써야 한다.
// 한글 처리도 내부에서 해주더라 !! ( "UTF-8"로 설정해서
String title = mpr.getParameter("title");
System.out.print(title);
System.out.print(path);
return null;
}
}
package study3;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LikeServlet extends HttpServlet{
int i = 0;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println(this.toString());
/*많은 사람들이 동시에 접속해도 동일한 문자열이 계속 찍힌다 -> 동일한 인스턴스가 재사용되고 있다.
* 메모리 관리에는 장점이다
* 한꺼번에 많이 들어와도 적게 메모리를 소모한다
* */
PrintWriter out = response.getWriter();
out.println("<html><body>");
/*왜 synchronized ?
* 동시 요청 시 여러개의 쓰레드가 하나의 서블릿 인스턴스를 사용할 수 있다.*/
synchronized(this){
i = i+1;
for(int i = 0 ; i < 20000; i ++){
out.println(this.i);
}
}
out.println("</body></html>");
out.flush();
out.close();
}
}
3.서블렛 여러 기능
<ConfigServlet.java>
package study3;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ConfigServlet extends HttpServlet{
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("service");
//컨텍스트 경로
String l = request.getContextPath();
System.out.println("getContextPath : " + l);
//ip 주소 다음 나오는 전체 경로
String m = request.getRequestURI();
System.out.println("getRequestURI : " + m);
//접속한 브라우저의 ip 주소값
String n = request.getRemoteAddr();
System.out.println("getRemoteAddr : " + n);
//접속한 브라우저와 운영체제 정보를 담은 문자열이 얻어진다
//이것을 이용하여 모바일로 접근한 건지 컴으로 접근 한 건지 알수 있고
//모바일용 화면과 컴용 화면을 구분하여 제공할 수 도 있다.
String o = request.getHeader("User-Agent");
System.out.println("User-Agent : " + o);
/*getContextPath : /study3
getRequestURI : /study3/config
getRemoteAddr : 0:0:0:0:0:0:0:1
User-Agent : Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko */
}
/*init
service
service
service
service -> 서블릿의 인스턴스는 재활용 된다.
인스턴스는 재활용을 위해 내부적으로 적재된다 => init
적재되는 시점에 호출되는 함수가 init - 최초 요청 시 에만 호출된다.*/
@Override
public void init(ServletConfig config) throws ServletException {
// String val = config.getInitParameter("apple");
// System.out.println(val);
/*WEB-INF 폴더의 절대 경로값을 얻어온다
* 브라우저가 접근 못하는 폴더가 업로드 파일을 놓기에 가장 적합
* 허락받고 (돈내고) 다운 받을 때 FileInputStream 으로 읽어 내보낸다
* FileInputStream : 절대 경로를 필요로한다
* getRealPath : 유용하게 쓰인다.*/
ServletContext application = config.getServletContext();
String path = application.getRealPath("/WEB-INF/");
System.out.println(path);
// System.out.println("init");
}
/*blabla
C:\workspace3\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\study3\WEB-INF\
service*/
}
<LikeServlet.java>
package study3;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LikeServlet extends HttpServlet{
int i = 0;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println(this.toString());
/*많은 사람들이 동시에 접속해도 동일한 문자열이 계속 찍힌다 -> 동일한 인스턴스가 재사용되고 있다.
* 메모리 관리에는 장점이다
* 한꺼번에 많이 들어와도 적게 메모리를 소모한다
* */
PrintWriter out = response.getWriter();
out.println("<html><body>");
/*왜 synchronized ?
* 동시 요청 시 여러개의 쓰레드가 하나의 서블릿 인스턴스를 사용할 수 있다.*/
synchronized(this){
i = i+1;
for(int i = 0 ; i < 20000; i ++){
out.println(this.i);
}
}
out.println("</body></html>");
out.flush();
out.close();
}
}
public class BangMyungVO { public Integer getNo() { return no; } public void setNo(Integer no) { this.no = no; } public String getGul() { return gul; } public void setGul(String gul) { this.gul = gul; } public String getTheTime() { return theTime; } public void setTheTime(String theTime) { this.theTime = theTime; } private Integer no = null; private String gul = null; private String theTime = null; }
<test_01.html>
<!DOCTYPE html> <head> <body> test_01.html <!-- cellspacing="0" : 셀 간 간격 cellpadding="12" : 셀의 벽과 내용과의 간격 border="1" : 경계줄의 굵기 bgcolor="#ccddee" 배경색, 각각 16진수이고 앞 두자리 : red, 다음 두자리 : green, 마지막 두자리 : blue => RGB 값을 섞은 값 rowspan="3", colspan="2" : 엑셀에서의 셀 병합과 같은 개념 rowspan은 상하, colspan은 좌우 셀과 병합한다. <font size = "20px" face = "Impact">apple</font> : 브라우저에 깔린 글꼴만 가능 align ="left| center | right" : 내용물의 좌우 정렬 속성을 정한다 width : 셀의 폭을 결정함 같은 오와 열에 있는 것들은 자동으로 지정된 크기에 맞춰진다(일일이 모든 칸에 크기를 줄 필요가 없다) --> <table border="0" cellspacing="2" cellpadding="12"> <tr bgcolor="#aabbcc"> <td width = "400px" rowspan="2"><font size = "20px" face = "Impact">apple</font></td> <td width = "250px">banana</td> </tr> <tr> <td bgcolor="#ccddee">kiwi</td> </tr> <tr> <td colspan="2" bgcolor="#ccddee" align="center">kiwi</td> </tr> </table> </body> </html>
- byte , short , int, long은 정수의 값을 가져다 저장할 수 있는 자료형
- 작은 타입 => 큰 타입 (자동 변환)
- 큰 타입 => 작은 타입 (강제 변환 -> X : 에러)
- (기본) 같은 타입형 변수만 연산 가능
2. 변수 : 값을 저장하는 기억공간
- 자료형 : 변수 선언
- 대입 : 값을 저장
문제
1. 연 6.6퍼 이자율에 초기금 100만원을 100년간 묵힐 때
public class Test1{
pulblic static void main(String[] args){
double money = 1000000; //초기금
double rate = 0.066; //이자율
for( int i = 0; i < 100; i++){
money += money * rate;
}
System.out.println((int)money);
}
}
2. 연 6.6% 이자율의 복리 (매 100만원 적금)
public class Test2{
public static void main(String[] args){
int addMoney = 1000000; //매 적금
double money = 0; // 초기금
double rate = 0.066;
for(int i = 0; i < 100; i++){
money += addMoney;
money += money * rate;
}
System.out.println(money);
long endTime = System.currentTimeMiilis();
}
}
Day 2
※코드 잘 짜는 법
- 잘 쪼갠다
- 자신의 보폭을 잘 파악한다
- 반복문 정리 => 일단 늘어놓고 정리
1. Java
-선언 , 대입, 연산
클래스에서 변수, 함수 선언 가능
클래스에서 변수, 함수 호출 연산, 초기화 등등 불가능
class Apple{
int i ;
i = 100; //error
int add(int i, int j){
return 100;
}
add(); //error
}
- 참조형 변수
Apple t = new Apple(); => 클래스를 선언하고 new를 이용하여 instance를 가리킴
class Apple{
int i;
int add(int i, int j){ return 100;};
}
public class Test023 {
public static void main(String[] args) {
Apple t = new Apple(); //에러 x -> 참조형 변수(포인터)
t.i = 100; // t가 가리키는 인스턴스가 가지고 있는 변수 i
System.out.println(t.add(100,20)); //t가 가리키는 인스턴스가 가지고 있는 함수
}
}
2. 요약
클래스를 선언하여 인스턴스를 만듬 => 이 떄, new 사용
클래스 내부 (멤버 함수(멤버 변수))
클래스 - 인스턴스 - new : 멤버 변수, 멤버 함수존재
인스턴스가 만들어지는 시점에 멤버변수 메모리 할당
함수 호출 시점에 로컬변수가 메모리 할당
참조형 변수 는 인스턴스를 가리키는 용도 / 클래스 이름으로 선언
자료형 변수 는 자바의 기본 8개 자료형
자료형 변수에서 대입 ( i = t ) -> t의 값을 복사해서 i에 대입
참조형 변수에서 대입 ( i = t ) -> t가 가리키는 대상을 i가 가리킴
생성자 함수 는 클래스의 멤버 함수 => 주로 멤버변수를 초기화 하는데 사용 (constructor)
class A {
int apple = 10;
}
//클래스 B는 클래스 A를 상속하여 만들었음을 명시.
// A에서 선언한 멤버변수는 멤버함수를 내려받겠다.
class B extends A{
int add(int i, int j){return 100;}
}
public class Test27 {
public static void main(String[] args) {
B t = new B();
System.out.println(t.apple);
}
}
2. 클래스 : 설계도 정의해 놓은 것
- 할 수 있는 것 : 참조형 변수 선언 / 인스턴스 생성 / 상속받아 클래스 선언
3. 생성자
<특징>
- return 타입 X
- 클래스명 (매개 변수) {.....} 로 동작
- 인스턴스 생성시점 호출
- 함수 아님 .. 인스턴스 멤버 변수를 초기화 시킬 때 주로 사용
class Apple4{
int data = 0;
// return이 존재하지 않는 함수를 서브루틴이라 한다.
//리턴타입을 void로 한다.
void print(){
System.out.println(this.data);
}
}
public class Test28 {
public static void main(String[] args) {
Apple t = new Apple();
t.data = 10;
t.print();
Apple l = new Apple();
l.data = 20;
l.print();
}
}
//출력 : 10 20
this : 멤버 함수 안에서 자신이 소속된 인스턴스에 대한 포인터
4.Java로 리스트 만들기
연결리스트
class Node{ //외워라!
int data = 0; // 대입은 원래 불가능하나 선언과 동시에 대입은 가능함
Node next = null; //가리키고 싶지않다.
Node( int i , Node n){ //생성자 일반적 예시
this.data = i;
this.next = n;
}
}
public class Test5 {
public static void main(String[] args) {
Node head = new Node(0,null); //Step 1
Node tail = head;
tail.next = new Node(10, null); //Step 2
tail = tail.next;
tail.next = new Node(20, null); //Step 3
tail = tail.next;
for( Node t =head.next ; t !=null ; t=t.next){ //Step 4
System.out.println(t.data);
}
}
}
/*
모든 참조형 변수에는 null 이라는 값이 대입 가능 : 가리키는 인스턴스 없다.
-어떻게 돌아가는지 상황파악을 그림으로 설명 가능할 것.
>> 출력 : 10 20
*/
- 객체 상태 변화
연결리스트 클래스화
class Node{
int data = 0;
Node next = null;
Node( int i , Node n){
this.data = i;
this.next = n;
}
}
class LinkedList {
Node head = null;
Node tail = null;
public LinkedList() {
this.head = new Node(0, null);
this.tail = this.head;
}
void add(int i){
tail.next = new Node(i, null);
tail = tail.next;
}
public void print() {
for (Node t = head.next; t !=null; t=t.next) {
System.out.println(t.data);
}
}
}
public class Test29 {
public static void main(String[] args) {
LinkedList l = new LinkedList(); //Step 1
l.add(10); //Step 2
l.add(20); //Step 3
l.print();
}
}//>> 출력 : 10 20
- 객체 상태 변화
5. Java 상속
class A{
A(){
System.out.println("A constructor");
}
}
class BB extends A{
B() {
System.out.println("B constructor");
}
}
public class Test31 {
public static void main(String[] args) {
new B();
}
}//>> A constructor B constructor
=> 왜? A constructor B constructor 이렇게 출력이 될까?
>> 생성자는 상속이 되지 않고 호출 되는 것이기 때문(멤버 함수가 아니라서)
-상속관계가 존재 시 조상 클래스 , 자손 클래스 자손의 인스턴스를 생성하면 조상의 생서자가 먼저 호출, 자손의 생성자가 호출된다
>>> 이 때 인스턴스는 2번 생성되는 것 처럼 보이지만 하나가 생성되고 조상과 자손을 호출한다.
class A{
void print(){
System.out.println("A print");
}
}
class B extends A{
void print(){
System.out.println("B print"); // method overriding
super.print();// 부모의 함수를 호출하고 싶을때
void print2(){
System.out.println("B print2");
}
}
public class Test32 {
public static void main(String[] args) {
B t = new B(); //자손 B호출
t.print();
A t2 = new A(); //조상 A 호출
t2.print();
A t3 = new B(); //자손 B 호출
t3.print();
//조상에서 선언된 멤버함수, 멤버변수만 호출 가능
//t3.print()2; -------> 에러남
//B t4 = (B) new A();//에러남 캐스팅되지않음
//t4.print(); //다운캐스팅은 일반적으로 불가
B t4 = (B) t3; //이 경우 다운캐스팅이됨
t4.print(); //JVM이 무슨형인지 추리할수 있기때문
}
}//결과값 : B print A print A print B print A print
6. Method overriding : 조상클래스에서 선언한 멤버 함수 재정의
- 각 인스턴스에서 정의된 method로 사용(변수는 오버라이딩 X)
- Super 을 이용하여 자손 클래스에서 조상 method 이용가능
7. 접근 제어자
상속
외부 호출
내가 쓰기
Private
X
X
O
protected
O
X
O
public
O
O
O
- 클래스 안의 멤버함수와 멤버 변수 앞에 붙임
- java 의 protected => 같은 패키지 내에선 접근 가능 / 다른 패키지 내에선 접근 불가
- 접근자 안적어? => friendly로 (같은 패키지로는 public / 다른 패키지는 private)
=> 때문에 Getter을 이용하여 자신의 값을 호출하게 만듬
class A{
private int data =100;
public int getData(){ return data;}
}
class B extends A{
private int data =200;
public int getData(){return data;}
}
public class Test{
public void static main(String[] args){
A t = new B();
System.out.println(t.getData());
}
}//결과값 : 200
-B 클래스의 getData가 호출이되서 혼란이 방지됨
-조상에서 getXXX 함수가 보이면 그런 변수가 있는줄 알고 xXX 변수는 피해간다
-이 경우 getData()로 부모클래스의 data를 부르려고 하면 getData()가 오버라이딩 되어있기 때문에 접근이 힘들어진다.
8. 추상클래스 : 선언되었지만 구현되어 있지 않은 메소드
abstract class A{
public abstract void print();
}
abstract class B{}
class C extends B{}
abstract class D extends C{}
public class Test1 {
public static void main(String[] args) {
// A t = new A();
A t = null;
}
}
-abstract 메소드가 하나라도 선언되어 있으면 그 메소드 가진 클래스는 반드시 abstract 클래스로 정의
-abstract 클래스는 인스턴스를 만들 수 없다
-참조형 변수 선언이 가능하다
-상속 또한 가능하다
abstract class A{
public abstract void print();
}
abstract class B extends A{} // <------- abstract class - abstract class
class C extends A{ // <------abstract 클래스가 아닌 클래스가 상속받으려면 구현해줘야 함
@Override
public void print() {
System.out.println("hi");
}
}
public class Test1 {
public static void main(String[] args) {
A t = new C(); // <------ 조상의 함수를 호출한 경우 , 자손의 함수가 호출, 오버라이딩 된 구현부가 호출
t.print();
}
}
<단리, 복리 추상 클래스로 구현>
abstract class Bank{
public abstract double calc(double money, int years, double rate);
public void print(){
double r = calc(100, 100, 0.066);
System.out.println(r);
}
}
class BokriBank extends Bank{
@Override
public double calc(double money, int years, double rate) {
return 59665.1234 * subCalc();
}
private int subCalc(){return 3;}
}
class DanriBank extends Bank{
@Override
public double calc(double money, int years, double rate) {
return 760.0 + money();
}
private int money(){return 100;}
}
public class Test2 {
public static void main(String[] args) {
Bank bk = new BokriBank();
bk.print();
Bank bk2 = new DanriBank();
bk2.print();
}
}
9. 인터페이스
interface ICalc{
public void print(); //인터페이스 안에는 모두 추상자료형이여야함
}
interface IUnknown{}
class Apple{}
class Calc extends Apple implements ICalc, IUnknown{
@Override
public void print() {
System.out.println("A");
}
}
public class Test3 {
public static void main(String[] args) {
ICalc ic = new Calc();
ic.print();
}
}
-일종의 추상 클래스 => 변수 선언, 상속 당할 수 있음 => 다만, 인스턴스 생성 불가
-인터페이스 상속해서 클래스를 선언될 때는 implements 이용
-다중 상속 가능, 클래스 상속과 인터페이스 동시 상속 가능
문제
<인터페이스 사용한 Decorator pattern>
interface IGreet {
public String greet();
}
class MerciGreet implements IGreet{
@Override
public String greet() {
return "Merci";
}
}
class HelloGreet implements IGreet{
@Override
public String greet() {
return "hello";
}
}
abstract class GreetDeco implements IGreet{
protected IGreet ig = null;
public GreetDeoo(IGreet ig) {
this.ig = ig;
}
}
// 자손의 생성자에서 조상의 생성자 중 매개변수 있는 생성자를 호출 원하면 supoer로 지정.
class StarDeco extends GreetDeoo{
public StarDeco(IGreet ig) {
super(ig);
}
@Override
public String greet() {
return "" + ig.greet() + "*";
}
}
class SharpDeco extends GreetDeoo{
public SharpDeco(IGreet ig) {
super(ig);
}
@Override
public String greet() {
return "" + ig.greet() + "#";
}
}
public class Test4 {
public static void main(String[] args) {
IGreet ig= new SharpDeco(new StarDeco(new HelloGreet()));
System.out.println(ig.greet());
}
}//hello*#
=> 추가 상식 : interface는 public 명시 안해도 컴파일시 자동으로 추가해줌
Day 4
1. 메소드 오버로딩 : 하나의 클래스 안에 이름은 같은데 매개변수 형태가 다른 함수 여러 개 공존 가능
class Temp{//하나의 클래스 안에 이름은 같은데 매개변수 형태가 다른 함수 여러 개 공존가능
public void print(){};
public void print(int i){
System.out.println(1);
};
public void print(double i){
System.out.println(2);
};
public void print(int i, int j){
System.out.println(3);
};
}
public class Test40 {
public static void main(String[] args) {
Temp t= new Temp();
t.print();
// float j = 3.14; 큰타입 Double(3.14) -> 작은타입 float(j)로 바로 변환 x
float i = (float) 3.14; //방법 1 강제형변환
float j = 3.14f; //방법2 float = float
t.print(j);// 매개변수가 딱 맞지 않으면 가장 가깝게 자동형변환 되는것을 찾아서 호출
}//>>결과 : 2
}
- 멤버 함수에는 오버라이딩 이라는 개념이 있지만, 멤버 변수에는 오버라이딩 개념이 없음
class A{
int i = 100;
}
class B extends A{
int i = 200;
void print(){};
}
public class Test40 {
public static void main(String[] args) {
A t1 = new B();
System.out.println(t.i);
//t 포인터가 가리키는 인스턴스를 감싸는 B클래스 인스턴스를 t2가 가리킨다.
B t2 = (B)t;
t2.print();
System.out.println(t2.i); //갑자기 i값이 변하므로 private해주는게 좋음
}
}
##요약
형변환 시 예기치 못한 변수의 변화가 생길 수 있으므로 같은 이름으로 하는 것은 금지
클래스 안에 올 수 있는 것 -변수 선언(멤버 변수) , 함수 선언(멤버 함수)
실행 하면 main이 먼저 올라오고
static으로 선언되면 클래스가 메모리에 올라올 때 인스턴스가 생성되기 전에 메모리 할당
자바 실행 환경은 클래스가 필요해지면 클래스 파일을 메모리에 올린다 -> 후에 인스턴스 생성 가능
static 멤버는 클래스 로딩 시에 메모리를 할당, 무조건 유일하다
non-static 멤버는 인스턴스가 생성 될 때 메모리를 할당받음 , 인스턴스마다 따로따로 존재
인스턴스가 100번 생성되도 클래스는 설계도이니 최초에 한번만 올라옴 / 이 때 스태틱은 전역변수처럼 1개만 올라옴
class Temp{
static int i = 100;
static void print(){
System.out.println(i);
}
void func(){
System.out.println("hi");
}
static class Temp2{
private int i = 3;
public void getI(){
}
static void print(){
System.out.println("hi");
};
}
}
public class Test40 {
public static void main(String[] args) {
int j = Temp.i;
Temp t = new Temp();
t.func();
Temp.print();
Temp.Temp2.print();
}
}// static 멤버는 클래스명. 심볼 형태로 접근 >> 결과 : hi 100 hi
-static 멤버 함수 안에서는 non-static한 멤버 함수, 멤버 변수에 접근 할 수 없다 (메모리에 아직 안올라와 있기 때문에)
-abstract 클래스는 인스턴스를 생성할 수 없다.
복습
class
instance
로컬변수 함수가 호출될 때 메모리할당
멤버변수 클래스내에 선언된 변수 인스턴스가 생성될떄 메모리 할당(static이 아닌경우)
매개변수 일종의 로컬변수로 함수호출시 생성
참조형변수 인스턴스를 가리키기위한 용도 : class 이름으로 선언
자료형변수 byte short int long float double boolean char
생성자함수 인스턴스가 생성될떄 호출 되는 함수, 주로 멤버변수를 초기화하는데 사용
extends 인터페이스 외 클래스 상속 1개만가능
implements 인터페이스 상속
interface(abstract만 가지고 있는 클래스)
abstract class(하나의 abstract method가 있는경우 무조건)
abstract method(선언은 되었지만 구현은 없는경우)
overriding( 부모로부터 상속)
overloading( 같은 이름의 메소드 다른 매개변수)
자료형변수_캐스팅 : 큰 형태에서 작은형태 x 작은 형태에서 큰형태 o
참조형 변수_캐스팅 (큰박스가 작은박스를 감싸는 모양)
자료형 변수의 대입 : 오른쪽의 값을 복사해서 왼쪽에 대입
참조형 변수의 대입 : 오른쪽이 가리키는 대상이왼쪽을 가리킴
private : 나만쓸수있음
public : 나쓸수있고 참조형변수도되고 자손도가능
protected : 나쓸수있고 자손도가능
friendly(default) : 같은패키지에서는 public 다른패키지에서는 private
A t = new B() 조상의 참조형 변수로 자손을 만드는것은 가능하고, 조상의 함수를 호출한 경우 자손의 함수가 호출되므로 오버라이딩 된 구현부가 호출이됨
2. 자바 배열
public class Test5{
public static void main(String[] args){
int[] i = new int[]{1,2,3,4}; //new 사용했으므로 자바의 배열은 인스턴스
//int[] i = {1,2,3,4}로 축약해서 사용할 수 있다.
for(int j : i){ //i = 참조형 변수
System.out.println(j);
}
System.out.println(i.length); //그래서 멤버 변수를 가지고 있음
}
}//배열 : 동일한 형태의 기억장소가 연속으로 할당된 기억공간 >>>결과 : 1 2 3 4 4
for문 구현할 시에는
for(int j = 0; j < i.length; j++){
if(j == 2){
break; //break는 반복문 탈출 , continue는 이하의 코드는 수행을 건너 뛰고 반복을 계속
}
System.out.println(i);
}
3. Object class
-자바의 기본적으로 제공되는 클래스
-자바,lang 패키지에 소속된 클래스는 import 없이 사용 가능
public class Test048 {
public static void main(String[] args) {
Object t = new Temp();
System.out.println(t.toString());// toString()은 Object에 선언되었고, 상속되었다.
Object t2 = new Temp();
System.out.println(t2.toString());
}
}>>결과값 : Temp@460141958 Temp@1163157884
-조상 클래스를 지정하지 않으면 object로부터 상속받는다
-object는 모든 클래스의 조상
-object는 어떤 타입의 인스턴스도 가르킬 수 있다.
-toString()은 오브젝트.클래스에 선언되어 있다.
4. Getter Setter
-멤버 함수는 private 권장 / 값을 읽을 때는 getter함수 제작
-인스턴스 내 변수값 일기 전용 -> getter만 만듬
-인스턴스 내 변수값 바꾸고 싶을 때는 -> setter를 쓰는 것
class Temp{
private Object data = null;
public Object getData(){
return data;
}
public void setData(Object obj){
this.data = obj;
}
}//오브젝트 클래스 getter / setter
주의점
class Temp{
private int data = 100;
public int getData(){
return data;
}
}
class Temp2 extends Temp{
private int data = 200;
public int getData(){
return data;
}
}
public class Test048 {
public static void main(String[] args) {
Temp t = new Temp();
System.out.println(t.getData());
Temp t2 = new Temp2();
System.out.println(t2.getData());
Temp2 t3 = new Temp2();
System.out.println(t3.getData());
}
}//결과값 : 100 200 200
5. String 클래스
-StringPool : 자바에서 String클래스를 유일하게 new 없이 ""로 인스턴스 가능
public class Test048 {
public static void main(String[] args) {
String t = "HelloWorld";
String t2 = "HelloWorld";
System.out.println(t == t2);
System.out.println(t.equals(t2));
System.out.println(t.hashCode());
System.out.println(t2.hashCode());
}//>>결과값 : true true 439329280 439329280
-""를 만나면 VM은 StringPool을 뒤져서 없으면 만들고, 있으면 재활용
-HTML 내용을 String으로 만들고 재활용 하는 쪽이 메모리 관리에 유용하다
-String으로 캐스팅
class Temp{
private Object data = null;
public Object getData(){
return data;
}
public void setData(Object obj){
this.data = obj;
}
}
class Temp2{
private String data = null;
public String getData(){
return data;
}
public void setData(String obj){
this.data = obj;
}
}
public class Test048 {
public static void main(String[] args) {
Temp2 t2 = new Temp2();
t2.setData("HelloWorld"); //스트링만 인스턴스로 저장 할 수 있음 (스트링은 상속불가)
String l2 = t2.getData(); //casting 불필요
Temp t = new Temp();
t.setData("HelloWorld"); //모든 인스턴스로 저장할 수 있음
String l = (String) t.getData(); //캐스팅 필요
}
}
6. Generic : 인스턴스 내부의 자료형을 동적으로 지정할 수 있음.
- Object + 구체적 자료형 결합
-< > 안에 지정 가능한 타입은 참조형 변수 타입이어야 한다.(자료형 안됨)
- System.out.print로 호출하면 자동으로 toString이 호출되도록 약속되어 있다.
class Temp< T extends Object>{
private T data = null;
public T getData(){return data;}
public void setData(T data){this.data = data;}
}
public class Test048 {
public static void main(String[] args) {
Temp<String> t = new Temp<String>();//참조형 변수만 가능, String, integer, double
t.setData("HelloWorld");
System.out.println(t.getData());
Temp<Object> t2 = new Temp<Object>();
t2.setData("HelloWorld");
String l2 = (String) t2.getData();
System.out.println(t2.getData());
}
}//>> 결과값 : HelloWorld HelloWorld
-Integer : int 클래스
-Double : double 클래스 있음
public class Test054 {
public static void main(String[] args) {
Object ob = new Integer(100);
Object ob2 = new Double(3.14);
int i = ((Integer) ob).intValue();
//왜 ? 함수 호출을(Integer)ob는 toString으로 String값이 넘어옴
System.out.println(i);
double j = ((Double)ob2).doubleValue();
System.out.println(j);
}
}
7. AutoBoxing
Integer i = 100;
Object t = 200; //object 변수에서도 autoboxing 동작함 , JDK 1.5에서 추가
System.out.println(i.getClass().getName());
System.out.println(t.getClass().getName());
//결과값 : java.lang.Integer java.lang.Integer
-Integer i = 100; => Integer i = new Integer(100); 로 컴파일러가 자동으로 바꿔줌
-값을 wrapper 클래스에 대입하는 코드는 자동으로 인스턴스 생성하여 값을 감싸줌 : Auto boxing
8.AutoUnboxing
Integer i = 100; //Integer i = new Integer(100);로 자동 줄바꿈
int j = i; //i.intValue();
System.out.println(j);//>> 결과 100
Object t = 200;
int k = t; //error => object타입으로 오토박싱된 인스턴스는 언박싱되지 않는다
//t.intValue()로 호출할 수 없다 -> JDK 1.5에서 추가됨
#근데 공부하다 보니 캐스팅과 박싱의 차이는 뭘까가 궁금해짐
-캐스팅은 단순히 타입 a -> 타입 b
-박싱은 원시 타입(boolean, char) -> 참조 타입(string, file)
-char 주워담아서 박싱하면 스트링 되고 , 스트링 박스를 언박싱하면 char가 된다
9. Command Pattern
interface ICalc{
public int execute(int i);
}
class AddCalc implements ICalc{
private int data;
public AddCalc(int data) {
this.data = data;
}
@Override
public int execute(int i) {
return i+data;
}
}
//쓰임 당하는 입장에서 쓰는 쪽에게 어떤 의견 제시하는 통로 필요 : 어노테이션
// 이것을 체계화 한 것이 1,5 이후에 도입된 Annotation 개념이 된다.
interface PrintStarts{} //어노테이션 인터페이스의 조상뻘 개념
class MinusCalc implements ICalc, PrintStarts{
private int data;
public MinusCalc(int data) {
this.data = data;
}
@Override
public int execute(int i) {
return i-data;
}
}
public class Test054 {
public static void main(String[] args) {
ICalc i = new AddCalc(3);
int r = 5;
r = i.execute(r);
System.out.println(r);
ICalc[] ls = new ICalc[5];
ls[0] = new AddCalc(2);
ls[1] = new MinusCalc(3);
ls[2] = new AddCalc(6);
ls[3] = new MinusCalc(1);
ls[4] = new AddCalc(7);
int y = 10;
for (int j = 0; j < ls.length; j++) {
y = ls[j].execute(y);
if(ls[j]instanceof PrintStarts){
System.out.print("**");
}
System.out.println(y);
}
}
}
/*
일반적으로 자료값은 변수로, 동작은 함수로 만든다.
동작을 하나의 인스턴스로 수행하게 하는 경우가 있다.
- 이런 설계기법을 Command Pattern이라고 한다.
리스트같은데 인스턴스들을 저장하여 매크로처럼 사용 할 수 있다.
*/
10. Build
class Temp1{
int data = 0;
// 아래 코드의 t와 this가 가리키는 대상은 같다.
// 따라서 t.add(10)은 10을 더한 후에 t로 바꿔 쓸 수 있다.
// StringBuffer의 append에서 볼 수 있다.
Temp1 add (int i){
data += i;
return this;
}
}
public class Test057 {
public static void main(String[] args) {
Temp1 t = new Temp1();
t.add(10).add(10).add(100);
System.out.println(t.data);
}
}//결과 : 120
11. String Buffer Class
public class Test057 {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
sb.append("apple");
sb.append("banana");
String l = sb.toString();
System.out.println(l);
System.out.println("apple" + "banana");
//코드는 컴파일러가 new StringBuffer().append("apple").append("banana").toString
//방식으로 한줄마다 new StringBuffer가 동작하지만 위의 코드는 한번만 동작
}
}//applebanana applebanana
12.String vs StringBuffer Test
public class Test057 {
public static void main(String[] args) {
long start = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 100000; i++) {
sb.append("apple");
}//StringBuffer : 하나의 인스턴스
long end = System.currentTimeMillis();
System.out.println(end - start);
start = System.currentTimeMillis();
String st = new String("");
for (int i = 0; i < 100000; i++) {
st += "apple";
}//String : 다수의 인스턴스
end = System.currentTimeMillis();
System.out.println(end - start);
}
}//결과값 : 8 11645 //StringBuffer가 훨씬 좋음
-java -verbosegc 클래스 이름 통해 가비지 콜렉터 과정을 볼 수 있음
-메모리가 부족할 때 메모리를 비우고 확보하는 일 모니터링
13.String
-SubString();
String l = "HelloWorld";
System.out.println(l.substring(2,5)); //llo
-indexOf(); : 만약 없는 문자열 찾을 때는 -1 리턴/ 문자열 안의 부분 문자열 위치를 리턴
String l = "HelloWorld";
System.out.println(l.indexOf("or")); //>>6
-starsWidth(); / endsWidth(); 시작이나 끝 문자열이 매개변수값과 같으면 true 아니면 false
String l = "HelloWorld";
System.out.println(l.startsWith("Hell"));
System.out.println(l.endsWith("ld")); //true true
-toCharArray(); : String을 char 배열로
String l = "HelloWorld";
char[] ch = l.toCharArray();
for (int i = 0; i < ch.length; i++) {
System.out.println(ch[i]);
}//결과값 : H e l l o W o r l d
문제
배열의 최대값 구하기
public class Test045 {
public static void main(String[] args) {
int[] i = new int[]{4,9,6,5};
int max = i[0];
for (int j = 1; j < i.length; j++) {
if(max < i[j]){
max = i[j];
}
}
System.out.println(max);
}
}//>>9
제너릭 연결리스트
package node;
class Node<T>{
T data = null;
Node<T> next = null;
Node(T i, Node<T> n){
data = i;
next = n;
}
}
class LinkedList<X>{
private Node<X> head = null;
private Node<X> tail = null;
public LinkedList() {
this.head = new Node<>(null, null);
this.tail = head;
}
public LinkedList<X> add(X input){
tail.next = new Node<>(input, null);
tail = tail.next;
return this;
}
public void print(){
for(Node<X> n = head.next; n != null; n = n.next){
System.out.println(n.data);
}
}
}
public class MyLinkedList {
public static void main(String[] args) {
LinkedList<String> ll= new LinkedList<>();
ll.add("test").add("this").add("how");
ll.print();
LinkedList<Integer> l2 = new LinkedList<>();
l2.add(3).add(2);
l2.print();
}
}
String의 indexOf와 동일한 동작 하게
package index;
class Finder{
public static int indexOf(char[] operand, char[] operator) {
int odLenth = operand.length;
int otLenth = operator.length;
int idx = -1;
for (int remainder = odLenth - otLenth; remainder >= 0; remainder--) {
if(operand[remainder] == operator[0]){
for(int i=1; otLenth-1 >= i; i++){
if(operand[remainder+i] == operator[i]){
if(i == otLenth-1){
idx = remainder;
break;
}
}else {
break;
}
}
}
}
return idx;
}
}
public class MyIndexOf {
public static void main(String[] args) {
int idx = Finder.indexOf("Hedoerrdwld".toCharArray(), "sdadsadsadorw".toCharArray());
System.out.println(idx);
}
}
class A{
}
class B extends A {
public void print() {
System.out.println(100);
}
}
public class Test061 {
public static void main(String[] args) {
A t= new A();
if*
B t2 = (B) t;
t2.print();
}
}
//결과값 : Exception in thread "main" java.lang.ClassCastException:
javaclass.A cannot be cast to javaclass.B at javaclass.Test061.main(Test061.java:16)
-instanceof : 캐스팅 에러 미리 방지
A t= new A();
//(B)t 이것이 가능하면 true/ 아니면 false
if (t instanceof B){
B t2 = (B) t;
t2.print();
}
-boolean : 비교연산 값을 리턴
-거의 모든 연산은 같은 자료형 끼리 가능
-double간의 연산 비교는 정확하지 않는다.
public class Test061 {
public static void main(String[] args) {
boolean i = true;
boolean j = false;
System.out.println(10 < 5);
System.out.println(10 / 3); // 나머지를 뺀 몫이 나옴
System.out.println(10 % 3); //나머지를 구하는 연산자
System.out.println(10.0 / 3);
System.out.println(3.33333333 * 3 == 10.0);
System.out.println(3.3333333333333335 * 3== 10.0); //Double 연산은 값을 보장할 수없다. 오차발생
}// c는 정수값 0 은 false, 0이아닌 모든 정수는 true
}// if(100)참
//결과값 : false 3 1 3.3333333333333335 false true
2.Package
-클래스의 묶음, 파인 맨 위에 지정
-한 파일안에 선언한 모든 클래스는 지정된 패키지 속함
-패키지를 지정하지 않으면 Unnamed 패키지에 소속, 사용시 제약이 많음
- javac -d . Test061.java
대상폴더아래 패키지이름으로 폴더생기고, 그 아래에 class파일이 들어간다.
package javaclass;
public class Test061 {
public int print(){
return 200;
}
public int print2(int i ){
return 300 * i;
}
public static int print3(){
return 100;
}// 패키지가 지정된 클래스 컴파일 : javac -d [폴더위치] Test061.java
}
3.import
-다른 패키지 클래스는 반드시 명시
-만일 그래도 못찾으면 class 를 명시해야한다.
javac -classpath C:\A\ Test061.java
-실행 : java -classpath .;C:\A\ Test061
-> 현재 폴더 명시해줘야함
-classpath 옵션을 안주면 -classpath . 이 자동으로 붙는다.
-Test 061A의 멤버변수가 접근되는지 살펴본다 : protected, friendly(default) -> 다른패키지에서 접근 x
-Static Initializer: 클래스가 로딩되는 시점에 실행되고 클래스를 강제로 로딩하려면 Class.forName("클래스명");함수를 이용한다.
package practice;
import javaclass.Test061;
public class Test064 {
public static void main(String[] args) {
Test061 t = new Test061();
t.print();
}
}
package temp;
public class Test066A{
//static initializer라 한다. 클래스가 로딩되는 시점에 호출됩니다.
static{
System.out.println("Test066A loaded");
}
public int print(){return 200;}
public int print2(int i){return 300*i;}
public static int print3(){return 100;}
} // C:\a\ 아래에 컴파일하자. javac -d c:\A\ Test066A.java
public class Test066{
public static void main(String[] args) throws Exception{
//클래스를 찾아내서 해당 클래스를 강제로 메모리에 로딩시킨다.
//찾아낸 코드의 static initializer가 동작하게됨
Class<?> cls = Class.forName("temp.Test066A");
/* Class : 로딩된 클래스의 관리자 역할을한다.
cls.newInstance() : cls가 관리하는 temp.Test066A의 인스턴스를 생성한다.
obj.getClass().getName() : obj가 가리키는 인스턴스를 생성시킨 클래스 명 //임포트없이도 다른 패 키지의 인스턴스를 생성 할 수 있음
*/
Object obj = cls.newInstance(); //new를 쓰지않고 인스턴스를 만드는방법
System.out.println( obj.getClass().getName());
}
}
import java.lang.reflect.Method;
public class Test066_2{
public static void main(String[] args) throws Exception{
Class<?> cls = Class.forName("temp.Test066A");
Object obj = cls.newInstance();
/* getMethods() : 클래스안에서 선언된 함수에 대한 포인터들을 추출한다.
*/
Method[] mtds = cls.getMethods(); //함수 포인터
for (int i = 0; i < mtds.length; i++) {
System.out.println(mtds[i]);
}
}
}
/*결과값 : Test066A loaded
public int temp.Test066A.print()
public int temp.Test066A.print2(int)
public static int temp.Test066A.print3()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()*/
package javaclass;
import java.lang.reflect.Method;
public class Test066_3 {
public static void main(String[] args) throws Exception{
Class<?> cls = Class.forName("temp.Test066A");
Object obj = cls.newInstance();
// Method는 C의 함수포인터의 역할을 한다.
// cls.getMethods()는 모든 멤버함수의 포인터를 넘긴다.
// cls.getMethod(...) : 단하나의 멤버함수의 포인터를 넘기다.
// ...에는 함수이름, 매개뱐수의 형태를 명시한다.
// Method mtd = cls.getMethod("print");
Method mtd = cls.getMethod("print2", int.class);
System.out.println(mtd);
Object r = mtd.invoke(obj, 20);
System.out.println(((Integer)r).intValue());
}
}
/*결과값 : Test066A loaded
public int temp.Test066A.print2(int)
6000*/
package javaclass;
import java.lang.reflect.Method;
public class Test066_3 {
public static void main(String[] args) throws Exception{
Class<?> cls = Class.forName("temp.Test066A");
// Object obj = cls.newInstance();
// Method는 C의 함수포인터의 역할을 한다.
// cls.getMethods()는 모든 멤버함수의 포인터를 넘긴다.
// cls.getMethod(...) : 단하나의 멤버함수의 포인터를 넘기다.
// ...에는 함수이름, 매개뱐수의 형태를 명시한다.
// Method mtd = cls.getMethod("print");
Method mtd = cls.getMethod("print3");
System.out.println(mtd);
Object r = mtd.invoke(cls);
System.out.println(((Integer)r).intValue());
}
}
/*결과값 : Test066A loaded
public static int temp.Test066A.print3()
100*/
4.annotation
클래스나 method에 붙임
클래스가 컴파일되거나 런될때, annotation의 유무나 annotation 설정된 값을 통하여 클래스가 좀더 다르게 실행
설정파일처럼 설정하는 경우도
사용자 annotation
annotation 정의
annotation를 class에서 사용
annotation을 이용해 실행
package temp;
public class Test067 {
@PrintStars
public int print(){
return 100;
}
}// javac -d C:\a\ -classpath C;\A\ Test067.java -> import할 파일 위치
-----------------------------------------------------------------------------------
package temp;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface PrintStars {
}
-----------------------------------------------------------------------------------
package javaclass;
import temp.PrintStars;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class Test067_2 {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("temp.Test067");
Object obj = cls.newInstance();
Method mtd = cls.getMethod("print");
Annotation anot = mtd.getAnnotation(PrintStars.class);
Object r= mtd.invoke(obj);
if(anot.toString().equals("@temp.PrintStars()")){
System.out.println("**");
}
System.out.println(((Integer)r).intValue());
System.out.println(anot);
System.out.println(mtd);
}
}// javac Test067_2.java 컴파일시
//java -classpath C:\A\;. Test067_2 //내가 실행시킬 위치는 뒤 불러올거는 클래스패스 뒤, 여러개 불러올거면 ;로구분
/*결과값 : **
100
@temp.PrintStars()
public int temp.Test067.print()*/
5.java.util.*
-List
arraylist : 내부 배열 이용 , 속도 빠름, 중간 삭제 수정 힘듬
LinkedList : node 이용, 속도 느림, 중간 삭제 수정 쉬움(포인터만 바꿔주면됨)
list 특징 : 1. 중복 허용 2. 순서 유 3. stack, queue 유용
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
//ArrayList 속도가 빠르다. 내부적으로 배열을 사용
//배열을 사용하기때문에 속도는 빠른데, 중간중간 삭제가일어나면 비효율적이다.
//LinkedList Node를 이용하기에 단순하게 쌓는 속도는 느리다.
//중간에 추가 삭제가 빈번한 경우에는 용이하다.
// 둘 다 List를 상속한다. List를 상속받은 클래스는 특징이 존재한다.
// - 중복되는 걸 허용한다.검색시에 들어간 순서대로 나온다.(순서대로 보관한다.)->스택이나 큐 만드는데 용이하다.
public class Test068 {
public static void main(String[] args) {
List<String> l = new LinkedList<>();
l.add("apple");
l.add("banana");
l.add("orange");
l.add("kiwi");
for (String t : l) {
System.out.println(t);
}
}
}//결과값 : apple banana orange kiwi
-Set
treeset : 트리를 이용해 검색 속도가 list보다 월등
hastset : 해쉬 알고리즘을 이용해 기억 장소 할당
set 특징 : 1. 중복 허용 x 2.순서 x
package javaclass;
import java.util.Set;
import java.util.TreeSet;
// Set 인터페이스를 상속받은 것 : TreeSet, HashSet
// 공통특징 : 순서 개념이 없다. 중복을 허용하지 않는다.
// 저장할때 용이 -> 검색속도가 List보다 월등함
// TreeSet : 트리를 이용하여 보관, HashSet은 Hash알고리즘을 이용
public class Test069 {
public static void main(String[] args) {
Set<String> l = new TreeSet<>();
l.add("apple");
l.add("banana");
l.add("orange");
l.add("kiwi");
l.add("apple"); //중복된값
for (String t : l) {
System.out.println(t);
}
}
//결과값 : banana orange apple kiwi
-향상된 for문의 표준 검색 방법
Iterator<String> it = l.iterator();
while (it.hasNext()) {
String next = it.next();
System.out.println(next);
}
//iterator를 이용한 삭제
package javaclass;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
// Set 인터페이스를 상속받은 것 : TreeSet, HashSet
// 공통특징 : 순서 개념이 없다. 중복을 허용하지 않는다.
// 저장할때 용이 -> 검색속도가 List보다 월등함
// TreeSet : 트리를 이용하여 보관, HashSet은 Hash알고리즘을 이용
public class Test069 {
public static void main(String[] args) {
Set<String> l = new HashSet<>();
l.add("apple");
l.add("banana");
l.add("orange");
l.add("kiwi");
l.add("apple"); //중복된값
Iterator<String> it = l.iterator();
while (it.hasNext()) {
String next = it.next();
if(next.indexOf("an") != -1){
it.remove();
}
System.out.println(next);
}
}
}
-Map
map 특징 : 1.순서 x 2.중복 x(덧 씌워짐)
package javaclass;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
//map도 순서개념이 없으며 반드시 key = value 형태로 저장되야함 사전과 같은 형태
//put에 함수로 저장, get 함수로 key에 해당하ㅏ는 value를 뽑아낸다.
//list, Set, Map 형태로 뭔가 저장하는 형태를 흔히 Collection이라고 한다.
public class Test070 {
public static void main(String[] args) {
Map<String, String> map = new Hashtable<>();
map.put("apple", "사과");
map.put("banana", "바나나") ;
map.put("orange", "오렌지") ;
map.put("kiwi", "키위") ;
map.put("banana", "브내으너") ;
String value = map.get("apple");
System.out.println(value);
Set<String> keys = map.keySet();
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
String next = it.next();
String v = map.get(next);
System.out.println(next+ ", " + v);
}
System.out.println(map);
}
}/*
결과값 : 사과
banana, 브내으너
apple, 사과
orange, 오렌지
kiwi, 키위
{banana=브내으너, apple=사과, orange=오렌지, kiwi=키위}
*/
-Math.random();
package javaclass;
public class Test071 {
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
double d = Math.random(); // 0부터 1까지의 소수값을 랜덤하게 출력한다.
int a = (int) (d * 100); // 0~100까지
System.out.println(a);
}
}
}
-Throw
-각종 에러는 클래스로 구형
-코드 수행시 에러가 발생하면 해당 예외클래스의 인스턴스를 throw해버린다
-예외는 함수 수행 시에 발생되고, 함수에 그 사실을 명시
-생성된 예의처리 못할 시 프로그램 종료
package javaclass;
class TempException extends RuntimeException{}
public class Test074{
public static void main(String[] args) {
int i = 0;
if(i==0){
throw new TempException();
}
System.out.println(0);
}
}
package javaclass;
//연료 고갈이라는 에러를 클래스로 명시
class FuelException extends Exception{}
// Exception이 깐깐하다 : 컴파일이 안된다....
// 함수 안에서 에러가 발생 할 수 있다면 그 사실을 선언부에 명시해야 컴파일된다.
public class Test074{
public void carDrive(int fuel) throws FuelException{ //thorws로 연료고갈이 생길수 있음을 명시
if(fuel == 0){
throw new FuelException();
}
System.out.println("gogo");
}
public static void main(String[] args) {
Test074 t = new Test074();
//throws FuelException으로 선언된 함수를 호출할 때는 반드시 에러가 발생할 수 이는 영역을 try{...}로 감싸준다.
//try에는 반드시 1개이상의 catch가 있어야한다.
//에러가 발생되면 에러 인스턴스를 throw한다.
//catch(FuelException e)에 있는 e 변수가 발생된 에러 인스턴스를 가리 킬 수 있으면 catch에 딸린{...} 영역이 동작한다.
//...에는 에러를 수습 할 수 있는 코드가 들어가는것이 바람직하다.
//catch (Exception e)써도 됨 상속받기 떄문에
try {
t.carDrive(100);
} catch (FuelException e) {
System.out.println("견인차를 불러라");
}
}
}
package javaclass;
class FuelException extends Exception{
public void solve(){
System.out.println("견인차를 불러라");
//에러 처리
}
}
public class Test074{
public void carDrive(int fuel) throws FuelException{
if(fuel == 0){
throw new FuelException();
}
System.out.println("gogo");
}
public static void main(String[] args) {
Test074 t = new Test074();
try {
t.carDrive(100);
} catch (FuelException e) {
e.solve();
}
}
}
문제
1. 복권 뽑기 1
public static int[] randomArray(int i, int max) {
Set<Integer> si = new HashSet<>();
while(si.size() < i){
si.add((int)(Math.random()* max));
}
Object[] arr = si.toArray();
int[] result = new int[i];
int start = 0;
for(Object obj : arr){
result[start] = (int) obj;
start++;
}
return result;
}
2. 복권 뽑기2
public static int[] randomArray2(int i, int max){
int[] total = new int[max+1];
int[] result = new int[i];
for (int j = 0; j <= max; j++) {
total[j] = 0;
}
int counter =0;
while (counter < i) {
int rand = (int) (Math.random() * max);
if(total[rand] == 0){
result[counter] = rand;
counter ++;
total[rand] = 1;
}
}
return result;
}
3.리스트 출력
public static String collectionString(List<String> ls) {
String result;
if(ls.isEmpty()){
return "[]";
}else {
StringBuilder sb = new StringBuilder();
sb.append("[");
int start= 1;
int end = ls.size();
for(String t : ls){
sb.append("'");
sb.append(t);
sb.append("'");
if(start == 1 && end ==1){
start++;
continue;
}
start++;
if(start > end) {
break;
}else {
sb.append(",");
}
}
sb.append("]");
result = sb.toString();
}
return result;
}
}
// 2가지 이상의 다른 방법으로 구현 1가지는 collection 금지
public class Test072_HW {
public static void main(String[] args) {
int[] rl = HW.randomArray2(10, 100);
for (int i = 0; i < rl.length; i++) {
System.out.println(rl[i]);
}
List<String> ls = new ArrayList<>();
ls.add("apple");
ls.add("banana");
ls.add("orange");
ls.add("kiwi");
String l = HW.collectionString(ls);
System.out.println(l);
}
}