Inner Class
클래스 안에 클래스를 구성하는 것

종류      ... 클래스가 정의되는 위치에 따른 분류    
                       |     +--i) Inner Member 클래스   
                       |            +---a) non-static클래스    
                       |             +---b) static 클래스    
                       |     +--ii)Inner Local 클래스      
                                       +--a) Named Local Class    
                                       |      (이름있는 로컬 클래스)     
                                         +--b) Anonymous Class           
                                              (이름 없는 클래스,         익명클래스,      무명안긴 클래스) 

파일 class 파일로 저장시
Outer$Inner.java로 저장된다.

package day20;

public class Outer {
	int a = 10;
	static int b = 10;
	class Inner{
		int  c=30;
		public void foo() {
			System.out.println("foo()");
		}
		public void print() {
			//Inner class의 c값을 출력
			Inner x= new Inner();
			
		}
	}///////////////////////
	
	static class SInner{
		int d =40;
		void var() {
			System.out.println("bar()");
		}
		
		static void baz() {
			System.out.println("baz()");
		}
		
	}////////////////////

}////////////////////////////

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
package day20;

public class InnerClassTest {
	public static void main(String[] args) {
		Outer o = new Outer();
		System.out.println(o.a);
		System.out.println(Outer.b);
		
		Outer.Inner oi = o.new Inner();
		System.out.println(oi.c);
		oi.foo();
		
		Outer.Inner oi2 = new Outer().new Inner();
		System.out.println(oi2.c);
		
		Outer.SInner os = new Outer.SInner();
		System.out.println(os.d);
		os.var();
		Outer.SInner.baz();
		
		o.print();
	}
}

Outer Inner은 안드로이드에서 작업할 때 많이 나온다.

이너 클래스로 핸들러를 구성하는 방법 예시
이벤트 처리 코드를 모아서 관리할 수 있다.

package day20;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/*
 * 이벤트 소스 : JButton, JTextField
 * 이벤트 : ActionEvent
 * 이벤트 핸들러 : ActionListener 인터페이스를 구현 
 *    이벤트핸들러 구성방법
 *    1) 이벤트 소스를 가진 클래스가 핸들러가 되는 방법
 *    2) 이너 클래스로 핸들러를 구성하는 방법
 *    3) 외부 별도 클래스로 핸들러를 구성하는 방법
 * */


public class MainFrame extends JFrame {
	JPanel p = new JPanel();
	JTextField tf;
	JButton open;
	SubFrame s;
	public MainFrame() {
		super("::MainFrame::");
		Container cp = getContentPane();
		cp.add(p, "Center");
		p.setBackground(Color.white);

		tf =new JTextField(30);
		p.add(tf);
		open = new JButton("Open");
		p.add(open);
		s = new SubFrame();
		//이벤트 핸들러
		//MainFrame.MyHandler my = this.new MyHandler();
		MyHandler my = new MyHandler();
		//리스너 부착
		open.addActionListener(my);
		tf.addActionListener(my);
		s.close.addActionListener(my);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	class MyHandler implements ActionListener{
		
		@Override
		public void actionPerformed(ActionEvent e) {
			Object obj = e.getSource();
			if(obj==open) {
				setTitle("open");
				s.setSize(300,300);//w, h
				s.setLocation(500,0);//x좌표, y좌표
				s.setVisible(true);
			}else if(obj==tf) {
				setTitle("tf");
				String text = tf.getText();
				//text+=tf.getText()+"\n";
				//s.ta.setText(text);
				s.ta.append(text+"\n");
				tf.setText("");
			}else if(obj==s.close) {
				//System.exit(0);
				s.setVisible(false);//안 보이게 해주고
				s.dispose(); // 가지고 있는 resource를 다 가져감
			}
		}
	}//inner class

	public static void main(String[] args) {
		MainFrame ae = new MainFrame();
		ae.setSize(500, 500);
		ae.setVisible(true);
	}
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

package day20;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SubFrame extends JFrame{
	
	JTextArea ta;
	JButton close;
	
	public SubFrame() {
		super("::SubFrame::");
		Container cp = this.getContentPane();
		ta = new JTextArea();
		JScrollPane sp = new JScrollPane(ta);
		cp.add(sp,"Center");
		close = new JButton("Close");
		cp.add(close,"South");
		//this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		//this.setVisible(false)효과를 주면서
		//SubFrame이 사용하고 있는 리소스들을 해제하는 역할을 함
	}
}


로컬 이너 클래스

 a) 이름있는 로컬 이너 클래스  b) 이름없는 로컬 이너 클래스  로 구분할 수 있는데, 
로컬 클래스는 지역변수와  비슷한 성격을 가지며, 활용범위가 정의되는 메소 드  블럭 내부로 제한 된다. 
로컬 클래스는 외부(Outer)클래스의 멤버변수와,  메소드의 final 로컬변수, 그리고 final 매개변수  의 사용이 가능하다.   
(로컬 클래스가 메소드의   지역변수 값을 변화시키지 않기 위해서...) 
 a)이름있는 로컬 이너 클래스의 경우    
- 우선 정의를 한 다음에만 사용할 수 있다.  
- 다른 클래스의 상속이 불가능하다.    
- 컴파일 하면 OuterClass$숫자+로컬클래스명의 클래스 파일이 생성된다.  
여기서 숫자는 인덱스를 의미하는데, 서로 다른 메소드인 경우 동일 명칭의 클래스가 존재할 수 있기 때문에
중간에 인덱스 역할의 숫자를 붙여 구분되도록 한다. 

 b)이름없는 로컬 이너 클래스(Anonymous 클래스)     
- 이름을 갖지 않는 이너 클래스     
- 한번만 객체 생성이 가능하다.     
- 객체를 생성하는 문장 뒤에 클래스의 블럭을 덧붙이는 방법으로 구성        
- new 키워드 뒤 생성자의 명칭이 기존 클래스명일 경우에는 Anonymous클래스가 자동적으로 클래스의 자식 클래스가 되며,    
  인터페이스일 경우에는 이 인터페이스를 상속하는 클래스로서, 부모 클래스가 Object이 된다. 

package day20;
//이너 로컬 클래스 : 메소드 블럭 안에 구성된 이너 클래스. 
//지역변수와 비슷한 특징을 갖는다.

public class Outer2 {
	String str="@@@";//멤버(인스턴스) 변수
	
	void sub() {
		class LocalInner{
			
		}
	}
	void func() {
		final int num=100; //지역변수 (local변수)
		System.out.println(str);
		System.out.println(num);
		
		class LocalInner {
			String lstr="###";
			void print() {
				System.out.println(lstr);
				System.out.println(str);
				//local 이너클래스에스는 
				//final이 아닌 지역변수는 접근 불가
				System.out.println(num);
			}
		}
		LocalInner l = new LocalInner();
		l.print();
	}
	
	public static void main(String[] args) {
		Outer2 o = new Outer2();
		o.func();
		//LocalInner의 print()호출하기 ===> 불가능
	}
}


이름없는 이너 클래스

package day20;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
//이벤트 핸들러를 이름없는 이너클래스로 구현해보자
public class AnonymousClass extends JFrame {
	JPanel p = new JPanel();
	JButton b1,b2,b3;
	Canvas can;
	public AnonymousClass() {
		super("::AnonymousClass::");
		Container cp = getContentPane();
		cp.add(p, "Center");
		p.setBackground(Color.white);
		
		can = new Canvas();
		can.setSize(100,100);
		can.setBackground(new Color(153,120,200));
		p.add(can);
		p.add(b1= new JButton("Red"));
		p.add(b2= new JButton("Green"));
		p.add(b3= new JButton("Exit"));
		//{}이름 없는 이것은 ActionListener을 상속받는 이름 없는 class
		b1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				can.setBackground(Color.red);
			}
		});
		//b2
		b2.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				can.setBackground(Color.green);
			}
		});
        //이벤트 람다식
		b3.addActionListener((e)->{
			System.exit(0);
		});
		
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String[] args) {
		AnonymousClass ae = new AnonymousClass();
		ae.setSize(500, 500);
		ae.setVisible(true);
	}
}



라디오 버튼 Event
 * 이벤트소스 : JRadioButton
 * 이벤트 :ItemEvent
 * 이벤트핸들러: ItemListener
 *  -추상메소드 : public void itemStateChanged(ItemEvent)
 * [실습] r1,r2,r3클릭하면 can의 배경색 바꾸기
 * 이벤트 핸들러를 inner class로 만드세요

package day20;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

import day16.MyJPanel;
/*
 * 이벤트소스 : JRadioButton
 * 이벤트 :ItemEvent
 * 이벤트핸들러: ItemListener
 * 			-추상메소드 : public void itemStateChanged(ItemEvent)
 * [실습] r1,r2,r3클릭하면 can의 배경색 바꾸기
 * 이벤트 핸들러를 inner class로 만드세요
 * 
 * 
 * 
 * */
public class RadioTest extends JFrame {
	JPanel p = new MyJPanel();
	JPanel p1 = new MyJPanel();
	JPanel p2 = new MyJPanel();
	JRadioButton b1,b2,b3;
	JButton RGB, open;
	Canvas can;
	ButtonGroup g;
	
	public RadioTest() {
		super("::RadioTest::");
		Container cp = getContentPane();
		cp.add(p, "Center");
		cp.add(p1, "North");
		cp.add(p2, "South");
		p.setBackground(Color.white);
		b1 = new JRadioButton("Red",true);
		b2 = new JRadioButton("Green",false);
		b3 = new JRadioButton("Blue",false);
		//라디오 버튼을 단일 선택하도록 하려면 그룹 설정 해야함
		g= new ButtonGroup();
		g.add(b1);
		g.add(b2);
		g.add(b3);
		p1.add(b1);
		p1.add(b2);
		p1.add(b3);
		
		can = new Canvas();
		p.add(can);
		can.setSize(200,200);
		can.setBackground(Color.red);
		
		b1.addItemListener((e)->{
			can.setBackground(Color.red);
		});
		b2.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				can.setBackground(Color.green);
			}
		});
		b3.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				can.setBackground(Color.blue);
			}
		});
		
		RGB = new JButton("RGB");
		p2.add(RGB);
		RGB.addActionListener((e)->{
			JColorChooser s = new JColorChooser();
			Color c = s.showDialog(this,"색을 고르세요",Color.white);
			can.setBackground(c);
		});
		open = new JButton("open");
		open.addActionListener((e)->{
			ColorDialog cd = new ColorDialog();
			cd.setSize(200,200);
			cd.setBackground(Color.white);
			cd.setVisible(true);
		});
		p2.add(open);
		
		
		
		
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String[] args) {
		RadioTest ae = new RadioTest();
		ae.setSize(500, 500);
		ae.setVisible(true);
	}
}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
package day20;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Container;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;

public class ColorDialog extends JDialog {
	JPanel p = new JPanel();
	JPanel p2 = new JPanel();
	JButton close;
	Canvas can2;
	public ColorDialog() {
		super();
		Container cp = getContentPane();
		cp.add(p, "Center");
		cp.add(p2, "South");
		p.setBackground(Color.black);
		close = new JButton("Close");
		can2 = new Canvas();
		//canvas 크기를 꼭 지정하시오
		can2.setSize(30,30);
		int a= (int)(Math.random()*256);
		int b= (int)(Math.random()*256);
		int c= (int)(Math.random()*256);
		can2.setBackground(new Color(a,b,c));
		p.add(can2);
		p2.add(close,"South");
		
		close.addActionListener((e)->{
			this.setVisible(false);
			this.dispose();
		});
		this.setDefaultCloseOperation(0);
	}

}

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

그룹 함수
- 단일행 함수와 달리 그룹함수는 여러 행 또는 테이블 전체에 대해
  함수가 적용되어 하나의 결과를 가져오는 함수를 말한다.

- 그룹함수의 종류
AVG( DISTINCT| ALL| N) : NULL값을 제외한 N개 행의 평균값
COUNT(DISTINCT| ALL| expr |*) :* =>NULL값을 포함한 행의 개수
MAX(DISTINCT| ALL|expr) : 최대값
MIN(DISTINCT| ALL|expr)  : 최소값
STDDEV(DISTINCT| ALL| n) : NULL값을 제외한 n의 표준편차
SUM(DISTINCT| ALL|n) :  NULL값을 제외한 n의 합계
VARIANCE() :  NULL값을 제외한 n의 분산

* distinct는 중복되지 않는 값만 반환한다.그러나
* all 은 해당함수로 모든 값을 고려하게 한다.
* expr이 있는 인수들의 자료형태는 char, varchar2, number,date
   형이 될 수 있다.
* count(*)를 제외한 모든 그룹함수들은 NULL값을 무시한다.
   NULL값을 하나의 값으로 치환하기 위해서는 NVL함수를 사용한다.
* 모든 자료형에 대해 MAX와 MIN을 사용할 수 있다.
   그러나 AVG, SUM, VARIANCE,STDDEV는 NUMBER만 사용가능하다.

  SELECT COUNT(MGR) FROM EMP; 
  ==> 13개. null값을 무시하고 셈

  SELECT COUNT(distinct MGR) from emp;
  ==> 6개. 중복되지 않는 값만 리턴.

  그러나 count(*) 는 null값을 인정한다.
  select count(*) from emp;

  ex)가령 test테이블아 아래와 같다면
  -------------
  a b c
  -------------
  null  null    null
  null  null    null
 -------------
 위의 경우 select count(*) from test;하면 =>2를 반환
 그러나     select count(a) from test;하면 => 0을 반환

 [실습]
 emp테이블에서 모든 SALESMAN에 대하여 급여의 평균,
 최고액,최저액,합계를 구하여 출력하세요.
 SELECT AVG(SAL),MAX(SAL),MIN(SAL),SUM(SAL) 
 FROM EMP WHERE JOB='SALESMAN';

 아래 문장을 실습해보고 분석해보세요.
 SELECT MIN(ENAME),MAX(ENAME), 
 MIN(HIREDATE),MAX(HIREDATE),
 MIN(SAL),MAX(SAL) FROM EMP;

[문제]
EMP테이블에 등록되어 있는 인원수, 보너스에 NULL이 아닌 인원수,
보너스의 평균,등록되어 있는 부서의 수를 구하여 출력하세요.
////////////////////////////////////////

GROUP BY

- 특정 컬럼이나 값 등을 기준으로 해당 레코드를 묶어서 자료를 
   관리할 때 사용하는 구문. 그룹함수와 함께 사용.
  상품 테이블에서 각 상품군별로 몇 개의 상품이 있는지 검사하거나, 
  직업군 별로 최대, 최소값을 구할 때 사용됨.

  주의 gourpp by 할 때 select 할 수 있는 칼럼은 제한이 있다
  group by 에 사용된 컬럼이나 그룹함수만 SELECT 할 수 잇다.

  group by 절에 명시된 컬럼값이 같을 때 그룹을 만들고 이 그룹으로부터 집합함수를 통해 
  다양한 결과를 얻는다.

16] 고객 테이블에서 직업의 종류와 각 직업에 속한 사람의 수를 
     보여주시오.
select job, count(*) from member group by job;

cf>count는 함수. 직업별로 사람수를 파악할 때 사용.

17] 고객 테이블에서 직업의 종류, 각 직업에 속한 최대 마일리지 정보를 보여주세요.
select job, max(mileage) from member group by job;

18] 상품 테이블에서 각 상품카테고리별로 총 몇 개의 상품이 있는지 보여주세요.
select category_fk, count(*) from products group by category_fk 
order by category_fk asc;

또한 최대 판매가와 최소 판매가를 함께 보여주세요.
select category_fk, count(*), max(output_price),min(output_price) 
from products group by category_fk order by category_fk asc;

19] 상품 테이블에서 각 공급업체 코드별로 공급한 상품의 평균입고가를 보여주세요.
select ep_code_fk, avg(input_price) from products group by ep_code_fk;

문제1] 사원 테이블에서 입사한 년도별로 사원 수를 보여주세요.

문제2] 사원 테이블에서 해당년도 각 월별로 입사한 사원수를 보여주세요.

문제3] 사원 테이블에서 업무별 최대 연봉, 최소 연봉을 출력하세요.

HAVING
- GROUP BY와 항상 함께 사용하는 구문.
   GROUP BY 의 결과에 조건을 주어 제한할 때 사용한다.

20] 고객 테이블에서 직업의 종류와 각 직업에 속한 사람의 수가 
     2명 이상인 직업군
      의 정보를 보여주시오.
      select job, count(*) from member group by job 
      having count(*) >1;

21] 고객 테이블에서 직업의 종류와 각 직업에 속한 최대 마일리지 정보를 보여주세요.
      단, 직업군의 최대 마일리지가 0인 경우는 제외시킵시다.
      select job, max(mileage) from member group by job having max(mileage)<>0;

문제1] 상품 테이블에서 각 카테고리별로 상품을 묶은 경우, 해당 카테고리의 상품이 2개인 
      상품군의 정보를 보여주세요.
      
문제2] 상품 테이블에서 각 공급업체 코드별로 상품 판매가의 평균값 중 단위가 100단위로 떨어
      지는 항목의 정보를 보여주세요.
 
ORDER BY
- 자료를 정렬하여 나타낼 때 필요한 구문.
- 오름차순 ASC
- 내림차순 DESC 
  두 가지 방식이 있다.
- ORDER BY절을 사용할 때는 SELECT구문의 가장 마지막에 위치

만약 사용자가 데이터가 나타나는 순서를 지정하지 않으면 
기본적으로 데이터는 테이블에 입력되어 있는 순서대로 표시되지만, 
같은 SELELCT문에 대하여 Oracle Server에서 처음의 검색결과와 다음의 
검색결과를 항상 똑같이 보여주는 것은 아니다. 
따라서 사용자가 검색한 데이터를 특정순서로 지정하여보고 싶으면 
ORDER BY절을기술하여야 한다. 

24] 상품 테이블에서 판매 가격이 저렴한 순서대로 상품을 정렬해서 
보여주세요.
select * from products  order by output_price asc;

25] 고객 테이블의 정보를 이름의 가나다 순으로 정렬해서 보여주세요.
      단, 이름이 같을 경우에는 나이가 많은 순서대로 보여주세요.
select * from member order by name asc, age desc;

..정렬된 자료를 다시 한번 정렬하는 내용임.

 26] 고객 테이블에서 직업의 종류와 각 직업에 속한 사람의 수가 
     많은 순서대로 보여주세요.
select job, count(*) from member group by job
order by count(*) desc;

문제1] 상품테이블에서 공급업체별로 평균판매가를 구하되 
평균판매가 오름차순으로 보여주세요.

 문제2] 상품 테이블에서 배송비의 내림차순으로 정렬하되, 같은 배송비가 있는 경우에는
마일리지의 내림차순으로 정렬하여 보여주세요.

count(distinct | all| N | *)

select count(empno) from emp;
--NULL 값을 제외하고 세준다.
select count(NVL(MGR,0)),count(comm) from emp;

create table test(
  ID NUMBER,
  NAME VARCHAR2(20)
);

insert into test(id,name) values(null,null);
commit;

select * from test;
select count(*) from test;
select count(id) from test;

select *from emp;

select sum(sal),avg(sal),max(sal),min(sal),count(*) from emp
where JOB = 'SALESMAN';

select empno,ename,mgr from emp;

select count(distinct mgr) from emp;

select ename, job, count(*) from emp
group by job;

select * from emp;
select deptno, count(*), max(sal), min(sal) from emp
group by deptno;

select * from emp2;
select substr(hiredate,1,2),count(*) from emp2
group by substr(hiredate,1,2);

select to_char(hiredate,'YYYY'), count(*)
from emp2
group by to_char(hiredate,'YYYY') 
order by 1;

select '20'||substr(hiredate,1,2)||'-'||substr(hiredate,4,2),count(*) from emp2
group by '20'||substr(hiredate,1,2)||'-'||substr(hiredate,4,2);

select to_char(hiredate,'YYYY-MM'), count(*)
from emp2
group by to_char(hiredate,'YYYY-MM')
order by 1;

--having 절은 group by 절이랑 같이 사용해야한다.
select job, count(*) from emp
group by job
having count(*)>=3;

select job, max(mileage) from member
group by job
having max(mileage)!=0;

select * from products;

select category_fk , max(output_price), min(output_price) from products
group by category_fk;

select ep_code_fk ,avg(output_price) from products
group by ep_code_fk
having mod(avg(output_price),10)=0;

+ Recent posts