변수 선언 시 타입을 결정해야 한다
8가지 타입 중 중요한 타입 세 가지
1. int: 정수
2. double: 실수
3. boolean: True/False (주로 if문, switch문 같은 조건문에서 사용)
호출하기 위해서 인스턴스화를 해야 한다
변수 작성 양식
- (접근제한자) 타입 변수이름 =(대입연산자) 값
(대입연산자가 오면 초기화를 하겠다는 것)
package com.step1;
public class Variable1 extends Object {
// 변수를 선언할 수 있다.
// 접근제한자 타입 변수이름 =
public static void main(String[] args) {
int i = 1;
int j = 2;
System.out.println(i+j); // 3출력된다
System.out.println(hap); // 에러 발생 - 선언하지 않았으니까
}
}
변수의 종류
1. 원시형 타입(primitive type)
: 값을 그대로 할당
: int, double, boolean
2. 참조형 타입(Reference Type)
: 값이 저장된 주소값을 할당(주소번지)
: 클래스인 것은 모두 여기에 해당됨
- 클래스 타입은 주소번지(reference)를 갖는다
(호출하면 값이 아닌 주소번지가 찍힌다)- 레퍼런스 변수를 가지려면 인스턴스화를 해야 한다
(인스턴스화를 할 때 사용하는 예약어가 new)
변수의 선언 위치에 따라, 또 변수 선언시 붙는 수정자에 따라서
전역 변수(global variable) - 인스턴스 변수 호출은 전역변수만 가능
지역 변수(local variable) - 인스턴스 변수에 지역변수 호출은 불가(컴파일 안 됨)
정적 변수(static variable) - 클래스 타입.변수명으로 사용함(싱글톤, 하나다, 공유된다)
전역변수는 초기화를 생략할 수 있다(생성자가 대신 해주니까) -> 디폴트값이 정해져 있다(초기값 0)
지역변수는 초기화를 생략할 수 없다
<예제1>
package com.step1;
public class Sonata {
int speed = 0;
int wheelNum = 4;
String carColor = "검정색";
public static void main(String[] args) {
Sonata myCar = null;
myCar = new Sonata();
Sonata herCar = new Sonata();
herCar.speed = 50;
System.out.println(myCar.speed);
System.out.println(herCar.speed);
}
}
출력: 0
50
<주석 참조>
package com.step1;
public class Sonata {
// 접근제한자 class 예약어를 사용해서 클래스 선언
// 클래스 이름: 대문자로 시작(낙타표기법)
// 선언부 - 선언부에 선언하는 변수는 전역변수(global variable, member variable)
// 자동차를 생각나게 하는 고유명사 - speed, wheelNum, carColor
// 타입 + 변수이름 + 대입연산자 + 값
int speed = 0; // 주차 돼있을 때 - 호출하면 값이 나온다 -> 원시형타입(primative data type)
int wheelNum = 4; // 바퀴 수 4개
String carColor = "검정색"; // 변수 선언 - 대문자로 시작하는 건(String) 클래스이다 -> 참조타입(reference data type)
public static void main(String[] args) {
Sonata myCar = null; // 선언만 한 것 -> 아직 생성하지 않았다
// 변수 myCar를 아직 사용할 수 없다 / 타입만 결정되었다
// myCar - 인스턴스화에 사용된 변수를 인스턴스변수라고 한다
// 인스턴스변수를 통해서 호출할 수 있는 건 전역변수 뿐이다
// 지역변수는 불가
myCar = new Sonata(); // 생성하였다. 사용할 수 있다
// myCar를 전역변수 호출하는데 사용하더라도 NullPointerException이 발생하지 않는다
// 런타임에러시 발생하는 게 exception임
Sonata herCar = new Sonata();
// 선언과 생성을 나눠서 작성하면 시점의 문제를 당할 수 있다 - NullPointerException
herCar.speed = 50;
System.out.println(myCar.speed); // 0
// 원시형 타입에는 한 번에 하나만 담을 수 있다 - 변수의 장애
// 동시에 2개의 값을 가질 수 없다
System.out.println(herCar.speed); // 0
}
}
<예제2>
package com.step1;
public class Variable2 {
static int i = 5; // 정적변수(static)
// main메소드에서 non-static타입은 호출이 불가 하지만 static 타입은 가능
// 전역 변수는 인스턴스화를 하면 접근 가능
int j = 1; // 전역변수(정적변수X)
public static void main(String[] args) {
System.out.println("i는 " + i); // 5출력
~~System.out.println(j);~~ // 에러
// 인스턴스화를 하자
Variable2 myCar = new Variable2(); // myCar 선언
System.out.println("j는 " + myCar.j); // 1출력
}
}
<예제3>
왜 아래 그림에서는 jft.initDisplay( );에 에러가 날까?
왜 2번에서는 에러가 날까?
선언한 JFrameTest2 클래스 안에 initDisplay( )가 구현되지 않았기 때문
<예제4> -> 다시 보기
package com.step1; import javax.swing.JFrame; public class JFrameTest2 { // 클래스 선언하기 좌중괄호, 우중괄호 JFrame jf = new JFrame(); // 선언부에서는 선언과 초기화를 두 줄에 나누어 적을 수 없다 ~~int i;~~ // 선언만 한 것 -> 전변 ~~i = 10;~~ // 초기화 int j = 10; // 새로 선언한 변수 jf.setSize(500, 400); jf.setVisible(true); public static void main(String[] args) { JFrameTest2 jft = new JFrameTest2(); ~~jft.initDisplay();~~ // 메소드 뒤에는 {}가 와야 함. 메소드 이름 뒤에 세미콜론이 오면 호출 // 이건 선언을 안 한 상태로 호출했으니 에러가 나는 것이다 } }
에러가 뜨는 이유는?
<예제5>
package com.step1;
import javax.swing.JFrame;
public class JFrameTest3 {
static JFrame jf = new JFrame();
public static void main(String[] args) {
JFrameTest3 jft = new JFrameTest3();
jf.setTitle("난 3번이야");
jf.setSize(500, 400);
jf.setVisible(true);
}
}
→ 창 출력 완료
<예제6>
package com.step1;
import javax.swing.JFrame;
public class JFrameTest4 {
static JFrame jf = new JFrame();
public static void main(String[] args) {
JFrameTest3 jft = new JFrameTest3();
// jft는 지역변수이다.
// 메소드 좌중괄호, 우중괄호 안에서 선언된 변수는 모두 지변(의 성격)이다.
jft.jf.setTitle("난 3번이야"); // jft는 3번을 참조하는 것이고, jf는 4번 참조
jft.jf.setSize(500, 400);
jft.jf.setVisible(true);
jf.setTitle("난 4번이야");
jf.setSize(500, 400);
jf.setVisible(true);
// 주소번지를 두 번 접근해서 메소드를 호출하는 소스임
// 호출되는 setTitle메소드는 JFrameTest3에서 인스턴스화한
// JFrame에 정의된 메소드를 호출하는 것
}
}
<예제7>
package com.step1;
import javax.swing.JFrame;
public class JFrameTest5 {
JFrame jf = new JFrame(); // 전변의 성격 - 메소드 안에 선언하지 않았다
// 인스턴스변수.변수명으로 호출이 가능함 -> 전변
public static void main(String[] args) {
// 내 안에 선언된 변수이더라도 static 영역 안에서 non-static 변수를 호출할 때는
// 인스턴스화를 해야 한다
JFrameTest5 jft = new JFrameTest5();
// 인스턴스화를 하려면? JFrameTest4는 적으면 안 된다
// 해결방법은 주소번지를 두 번 접근해야만 한다
jft.jf.setTitle("난 5번이야");
jft.jf.setSize(500, 400);
jft.jf.setVisible(true);
}
}
<예제8> 탭 만들기
package com.step1; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; public class JFrameTest6 implements ActionListener { static JFrameTest6 jft = new JFrameTest6(); JFrame jf = new JFrame(); JButton jbtnAccount = new JButton("연산하기"); JButton jbtnExit = new JButton("종료하기"); // 인스턴스변수.변수명으로 호출이 가능함 -> 전변 public static void main(String[] args) { JFrameTest6 jft = new JFrameTest6(); jft.jf.setTitle("난 5번이야"); jft.jbtnAccount.addActionListener(jft); jft.jf.add("North",jft.jbtnExit); jft.jf.add("South",jft.jbtnAccount); jft.jf.setSize(500, 400); jft.jf.setVisible(true); } // 버튼을 누르는 건 사용자이고, 버튼이 눌렀는지 느끼는 건 JVM이다 @Override public void actionPerformed(ActionEvent e) { // 눌려진 버튼의 주소번지를 JVM으로부터 알아낸다 Object obj = e.getSource(); // 눌려진 버튼의 주소번지를 가져옴 // 오른쪽에 있는 값과 왼쪽에 있는 값이 같니? -> 대입연산자를 두 번 적는다 // 파라미터는 사용자가 입력한 값을 받아오는 자리 if(obj == jft.jbtnAccount) { System.out.println("버튼을 눌렀어요."); } } }출력
<예제9>
package com.step1; public class Variable3 { public void account(int i, int j) { System.out.println("account 호출 성공"); System.out.println(i); System.out.println(j); } public static void main(String[] args) { Variable3 v = new Variable3(); v.account(1,2); } } 출력: account 호출 성공 1 2
<예제9 주석 설명>
package com.step1;
public class Variable3 {
public void account(int i, int j) {
// 메소드 타입과 개수까지도 결정할 수 있어야 한다
// 사용자, 즉 개발자가 임의의 메소드를 얼마든지 선언할 수 있고 구현할 수 있음
// 파라미터 자리에 선언된 변수는 지역변수
// 값이 결정되지 않음 → 언제 결정되나요?
// → v.account(1,2);에서 초기화됨
System.out.println("account 호출 성공");
System.out.println(i); // 1
System.out.println(j); // 2
// call by value: 호출할 때 값이 복사/결정/초기화가 된다
}
// 컴파일을 하는 언어는 컴파일 타임에 문법 체크를 한다는 뜻
public static void main(String[] args) {
// 내가 정의한 메소드 account 호출하기
// 내 안에 정의된 메소드라 하더라도 static 영역에서 // static 없는 메소드를 호출하려면 인스턴스화
~~account(1.2);~~
// 주소번지 or 인스턴스변수 와야한다(해당메소드가 선언된 소유주 의미)
// 인스턴스화 해야한다
Variable3 v = new Variable3();
v.account(1,2);
~~v.account();~~ // 개수가 맞지 않음
~~v.account(5);~~ // 개수가 맞지 않음
~~v.account(5,3,5);~~ // 개수가 맞지 않음
// 파라미터의 개수가 다르면 같은 이름의 메소드라 하더라도 JVM이 다른 메소드로 인지한다
~~v.account(true, false);~~
}
}
Double
<예제1> package com.step1; public class Double3 { public static void main(String[] args) { int i = 1; double d = 3.14; // 강제형전환시에는 0.14는 int타입에 담을 수 없다 i = (int)d; // 여기서 괄호는 캐스팅 연산자라 부름 - 강제형 전환 System.out.println(i); // 출력: 3 System.out.println(d); // 출력: 3.14 } }
- 캐스팅 연산 시, 괄호 안에는 왼쪽 타입명을 적는다(대입연산자는 오른쪽 값을 왼쪽에 대입하는 것이니까
<예제2> 세 학생 점수의 평균 구하기 package com.step1; public class Double4 { public static void main(String[] args) { int jumsu1 = 70; int jumsu2 = 85; int jumsu3 = 90; int total = jumsu1 + jumsu2 + jumsu3; double d = 3.14; System.out.println(total/3.0); // 출력(double): 81.66666666666667 System.out.println(total/3); // 출력(int): 81 d = 150.0/3; d = 151/3.0; d = 152/3; // 오른쪽에 더블도 되고 int도 됨 total = (int)(150.0/3); // 강제 변환 - 원래는 total이 int기 때문에 불가능 } }
- int + double = double
- int - double = double
- int * double = double
- int / double = double
🖱 단축키