열심히 끝까지
디바이스 융합 자바(Java) day08 - 힙,스택,this.,this(),인스턴스 변수,클래스 변수, 본문
디바이스 융합 자바(Java) day08 - 힙,스택,this.,this(),인스턴스 변수,클래스 변수,
노유림 2022. 6. 16. 17:23[지난 수업]
클래스
- 객체지향 프로그래밍(코딩)
: 대상체를 갖고 싶어 함
-> 클래스를 잘 정의(파악)하는 것
ex) Car클래스 생성!
>> 어떤 값들을 저장할 수 있는가?
- 주인(name)
- 현재 속도 0(speed)
- 최고 속도 200(maxspeed)
> name, speed, maxspeed : 멤버변수, 속성, 필드, 어드리뷰트(애트리뷰트)
>> 어떤 행동들을 수행할지(기능 수행)? : 괄호 포함(함수, 메서드)
- 속도++()
- 속도--()
- 현재 상태를 출력()
속도를 증가시키는 코드
void speedUp() { // 멤버함수, 메서드
// 1. 기본형
// 2. 기능구현
// 3. input, output이 올바른지 체크
// -> 값을 받을 필요도, 돌려줄 필요도 없기 때문에 바꿀 것 없음!
speed += 10;
if(this.speed>this.maxSpeed) {
this.speed=this.maxSpeed;
System.out.println("과속!");
}
}
void speedUp(int speed) {
// 기본형 -> 기능 구현 -> input, output이 올바른지 체크
this.speed += speed; // 멤버변수 파란색, 통상변수 갈색
if(this.speed>this.maxSpeed) {
this.speed=this.maxSpeed;
System.out.println("과속!");
}
}
>> speedUp() 오버로딩★
Car car1 = new Car(); // 기본(디폴트) 생성자
: 멤버변수가 내가 원하는 값대로 초기화되지 않는다.
: 그래서 다음과 같이 만들고 싶어짐
↓
Car car1 = new Car("홍길동", 0, 200);
-> 생성자를 사용하는 이유 : 멤버변수를 원하는 값으로 초기화 가능 + "강제"
이 형태를 사용하기 위해서는 위에 생성자를 만들어주어야 함
ex ) Car(String name, int speed, int maxSpeed){
this.name = name;
this.speed = speed;
this.maxSpeed = maxSpeed;
}
Car(String name){
this.name = name;
this.speed = 0;
this.maxSpeed = 200;
}
>> 이렇게 생성자의 이름이 같지만 형태가 달라 두 개 이상 생기게 된 이 것을
"생성자 오버로딩"이라고 한다.
---------- 올코딩
package class01;
class Car{
String name; // 멤버변수, 속성, 필드, 어트리뷰트
int speed;
int maxSpeed;
void speedUp() { // 멤버함수, 메서드
// 1. 기본형
// 2. 기능구현
// 3. input, output이 올바른지 체크
// -> 값을 받을 필요도, 돌려줄 필요도 없기 때문에 바꿀 것 없음!
this.speed += 10;
if(this.speed>this.maxSpeed) {
this.speed=this.maxSpeed;
System.out.println("과속!");
}
}
void speedUp(int speed) {
// 기본형 -> 기능 구현 -> input, output이 올바른지 체크
this.speed += speed; // 멤버변수 파란색, 통상변수 갈색
if(this.speed>this.maxSpeed) {
this.speed=this.maxSpeed;
System.out.println("과속!");
}
}
void showInfo() {
System.out.println(this.name + "님의 현재 차량 상태 : [" + this.speed + "/" + this.maxSpeed + "]");
}
// 생성자 오버로딩
Car(String name){
this.name = name;
this.speed = 0;
this.maxSpeed = 200;
}
Car(String name, int speed, int maxSpeed){
this.name = name;
this.speed = speed;
this.maxSpeed = maxSpeed;
}
}
public class Test01 {
public static void main(String[] args) {
// Car car1 = new Car(); // 기본(디폴트) 생성자
// 멤버변수가 내가 원하는 값대로 초기화되지 않는다.
// 그래서 다음과 같이 만들고 싶어짐
Car car1 = new Car("홍길동", 0, 200);
// -> 생성자를 사용하는 이유 : 멤버변수를 원하는 값으로 초기화 가능 + 강제
Car car2 = new Car("아리");
car1.speedUp(130);
car2.speedUp(130);
car1.showInfo();
car2.showInfo();
}
}
*강사님! 원래는 car.showInfo();해야하는 걸
System.out.println(car1);을 했더니! 주소가 떠요!?
ex ) [I@5aaa6dsf]
=> 스택과 힙을 알면 이해하기 쉽다!
혹시.....
- 스택 오버플로우(=StackOverflow)를 본 적있는가?(Exception에) - 재귀함수에서 봤었다!!
>> 스택과 힙이라는 공간 두 개 존재
- 스택(Stack)
: 실행할 때 쓰는 공간
: 스택 오버플로우는 스택 공간에 갑자기 많은 데이터가 들어와서 과부화 걸린 상태
- 힙(heap) (like 배열)
: 개발자 영역이라고도 불린다.
: new 라는 것을 쓰면 객체 생성
: 객체를 생성한다는 것은? heap 영역을 쓴다는 것
: 스택에 주소를 넘겨주어 필요할 때 오도록 한다.
---위를 위해 강사님께서 들어준 예시
package class01;
class A{
int x;
int y;
void show() {
System.out.println(x+" / "+y);
}
}
public class Test02 {
public static void main(String[] args) {
A a1=new A();
A a2=new A();
a1.x=10;
a1.y=20;
a2.x=11;
a2.y=12;
int[] data=new int[3];
System.out.println(data);
a1.show();
System.out.println(a1);
}
}
-----------------------------------
[오늘 수업]
- 클래스에서 생성자를 만들 때
생성자 내부의 반복되는 것들을 줄이는 방법!!
this.
-> 내가 가진 속성을 불러오겠다!
: this == 자기 자신 객체
: this()
-> 함수(괄호가 있으면 무조건 함수!)
-> 자기자신() == 생성자
=> this() == 본인의 생성자
- 쓰는 방법
1. 인자가 많은 생성자 놔두고
2. 다른 생성자에서 1번의 생성자를 재사용
package class02;
class Point{
int x;
int y;
void showInfo() {
System.out.println("P(" + this.x + ", " + this.y + ")");
}
Point(){
this(0, 0); // 본인 생성자( ex ) 정수 두 개인 생성자) 불러오기
System.out.println("기본생성자");
}
Point(int x){
this(x, x);
System.out.println("인자가 1개인 생성자");
}
Point(int x, int y){
this.x = x;
this.y = y;
System.out.println("인자가 2개인 생성자");
}
}
public class Test03 {
public static void main(String[] args) {
Point p1 = new Point(10, 20);
Point p2 = new Point();
Point p3 = new Point(123);
p1.showInfo();
p2.showInfo();
p3.showInfo();
}
}
26번 실행
28번 실행 -> 17로 이동 : 인자가 2개인 생성자
29번 실행 -> 9 -> 10 -> 17 :
-> 11 : 기본생성자
30번 실행 -> 13 -> 14 -> 17 :
-> 15 : 인자가 1개인 생성자
-----------Test01을 this()를 이용하여 재코딩
package class01;
class Car{
String name; // 멤버변수, 속성, 필드, 어트리뷰트
int speed;
int maxSpeed;
void speedUp() { // 멤버함수, 메서드
// 1. 기본형
// 2. 기능구현
// 3. input, output이 올바른지 체크
// -> 값을 받을 필요도, 돌려줄 필요도 없기 때문에 바꿀 것 없음!
this.speed += 10;
if(this.speed>this.maxSpeed) {
this.speed=this.maxSpeed;
System.out.println("과속!");
}
}
void speedUp(int speed) {
// 기본형 -> 기능 구현 -> input, output이 올바른지 체크
this.speed += speed; // 멤버변수 파란색, 통상변수 갈색
if(this.speed>this.maxSpeed) {
this.speed=this.maxSpeed;
System.out.println("과속!");
}
}
void showInfo() {
System.out.println(this.name + "님의 현재 차량 상태 : [" + this.speed + "/" + this.maxSpeed + "]");
}
// 생성자 오버로딩
Car(String name){
// 1. 인자가 많은 생성자만 놔두고,
// 2. 다른 생성자에서 1번의 생성자를 재사용
this(name, 0, 120);
}
Car(String name, int speed, int maxSpeed){
this.name = name;
this.speed = speed;
this.maxSpeed = maxSpeed;
}
}
public class Test01 {
public static void main(String[] args) {
// Car car1 = new Car(); // 기본(디폴트) 생성자
// 멤버변수가 내가 원하는 값대로 초기화되지 않는다.
// 그래서 다음과 같이 만들고 싶어짐
Car car1 = new Car("홍길동", 0, 200);
// -> 생성자를 사용하는 이유 : 멤버변수를 원하는 값으로 초기화 가능 + 강제
Car car2 = new Car("아리");
car1.speedUp(130);
car2.speedUp(130);
car1.showInfo();
car2.showInfo();
}
}
------강사님 문제
package class01;
class A{
int x;
int y;
void show() {
System.out.println(x+" / "+y);
}
A(){
this(1,2);
System.out.println("111");
}
A(int x){
this(x,3);
System.out.println("222");
}
A(int x,int y){
this.x=x;
this.y=y;
System.out.println("333");
}
}
public class Test02 {
public static void main(String[] args) {
A a1=new A(13);
A a2=new A();
a1.show();
a2.show();
}
}
어떻게 출력되는가?
333
222
333
111
13 / 3
1 / 2
그림판
-----------강사님의 코딩문제
main(){
Student stu1=new Student("홍길동");
Student stu2=new Student("아리",20);
Student stu3=new Student("티모",21,95);
stu1.show();
stu2.show();
stu3.show();
}
-> Console
홍길동 학생부 저장완료!
아리 학생부 저장완료!
티모 학생부 저장완료!
홍길동: Lv.1 SCORE: 0
아리: Lv.20 SCORE: 0
티모: Lv.21 SCORE: 95
---가 나오도록 코딩해보기
package class02;
class Student{
String name; // 이름
int level; // 레벨
int score; // 점수
void show() { // 메서드 show() 작성 this.를 붙이지 않아도 되지만 가독성을 위해!
System.out.println(this.name + " : Lv." + this.level + " SCORE : " + this.score);
}
Student(String name){
this(name, 1, 0); // 인자가 1개인 생성자
}
Student(String name, int level){
this(name, level, 0); // 인자가 2개인 생성자
}
Student(String name, int level, int score){ // 인자가 3개인 생성자
this.name = name;
this.level = level;
this.score = score;
System.out.println(this.name + " 생성완료!");
// name으로 써도 되지만 this.name으로 가독성 증가
}
}
public class Test04 {
public static void main(String[] args) {
// 생성자 -> 멤버변수를 초기화하기 위해서
Student stu1 = new Student("홍길동"); // 인자가 1개인 생성자
Student stu2 = new Student("아리", 20); // 인자가 2개인 생성자
Student stu3 = new Student("티모", 21, 95); // 인자가 3개인 생성자
System.out.println();
stu1.show();
stu2.show();
stu3.show();
}
}
----------------------
- 멤버변수의 종류
1. instance(객체) 변수
: 객체의 멤버변수는 객체마다 고유한 값을 가진다.
>> 객체에 저장된다.
: 객체끼리의 값을 공유하지 않는다!
2. class 변수 ( = 공유자원 이라고도 부른다.)
: 객체끼리 값을 "공유"한다는 것
=> a객체의 변화가 b객체에도 영향을 준다.
: 클래스의 변수 앞에 static을 붙인다.
=> static으로 인해 객체와 무관하게 되어버렸다.
>> 클래스에 저장된다.
=> 그 값으로 고정되어 버린다.
>> a1의 y값도 마지막에 입력받은 a2의 y값으로
고정되어 버린 y값을 받는다.
>> 인스턴스 변수가 압도적으로 많이 쓰여서 멤버변수 == 인스턴스 변수 처럼 되어버린 것
- [공유] 개념
ex ) 같은 캐릭터인데 속성이나 들고있는 아이템이 다르다
>> 속성과 아이템이 객체
>> 같은 캐릭터의 기본 공격력, 체력, 방어력은 같다
package class02;
// 멤버변수 : instance(객체) 변수 / class(클래스) 변수
class A{
// 인스턴스(객체) 변수 == num1, num2
int num1; // 멤버변수 : 객체마다 고유한 값 >> 객체끼리 값을 공유하지 않는다.
// 클래스 변수
static int num2;
void showInfo() {
System.out.println("num1 = " + this.num1);
System.out.println("num2 = " + this.num2);
}
A(int num1, int num2){
this.num1 = num1;
this.num2 = num2;
}
}
public class Test05 {
public static void main(String[] args) {
A a1 = new A(1, 2);
A a2 = new A(10, 20);
a1.showInfo();
a2.showInfo();
}
}
>> 출력
num1 = 1
num2 = 20
num1 = 10
num2 = 20
만약 이렇게 되면??
package class02;
// 멤버변수 : instance(객체) 변수 / class(클래스) 변수
class A{
// 인스턴스(객체) 변수 == num1, num2
int num1; // 멤버변수 : 객체마다 고유한 값 >> 객체끼리 값을 공유하지 않는다.
// 클래스 변수
static int num2;
void showInfo() {
System.out.println("num1 = " + this.num1);
System.out.println("num2 = " + this.num2);
}
A(int num1, int num2){
this.num1 = num1;
this.num2 = num2;
}
}
public class Test05 {
public static void main(String[] args) {
A a1 = new A(1, 2);
A a2 = new A(10, 20);
a1.num1 += 100;
a1.num2 = 2;
a1.showInfo();
a2.showInfo();
}
}
>> 출력
num1 = 1
num2 = 2
num1 = 10
num2 = 2
--------------또다른 예시
package class02;
class Dog{ // 흔한 코드는 아니지만 보여주기 위해 작성
String name;
static String[] action = new String[5]; // 어떤 값이던 서로 공유
static int index; // 배운 개수, 이 값도 서로 공유!
void showInfo() {
System.out.println(name + " 강아지");
for(int i = 0; i < index; i++) {
System.out.println(action[i]);
}
}
}
public class Test06 {
public static void main(String[] args) {
Dog dog1 = new Dog();
dog1.name = "요요";
Dog dog2 = new Dog();
dog2.name = "꼬미";
dog1.action[dog1.index] = "기다려!";
dog1.index++;
dog2.action[dog2.index] = "앉아!";
dog2.index++;
dog1.showInfo();
dog2.showInfo();
}
}
---------------강사님 문제
class Card{
}
main(){
// 홍길동씨는 최초에 20만원 보유
Card card1=new Card("홍길동");
Card card2=new Card("홍길동",20000);
card1.use(); // 10000원 사용: 남은 금액 190000원
card1.use(100000); // 100000원 사용: 남은 금액 90000원
card2.use(50000); // 50000원 사용: 한도초과! 남은 금액 90000원
card2.use(); // 10000원 사용: 남은 금액 80000원
card1.use(90000); // 90000원 사용: 잔액부족! 남은 금액 80000원
card1.showInfo(); // 홍길동님[남은금액: 80000원]
card2.showInfo(); // 홍길동님[남은금액: 80000원]
}
-------내 답안
package class02;
class Card{
String name;
static int account; // 초기화는 가능하나 이렇게 쓰면 클래스 변수처럼 보임
int maxPay;
void showInfo() { // 이름, 잔액 금액 출력
System.out.println(this.name + "님[남은금액 : " + this.account + "]");
}
Card(String name){ // 카드 이름 하나만 입력받은 경우
this(name, 200000); // this(name, maxPay) 받아오기
}
Card(String name, int maxPay){ // 카드 이름과 한도 두개 입력받은 경우
this.name = name;
this.maxPay = maxPay;
}
void use() { // 사용하는 금액 기본(디폴트) 메서드
this.use(10000); // this에 use(pay)가져오기
}
void use(int pay){ // 사용하는 금액 메서드 use(pay)메서드 가져오기
System.out.print(pay + "원 사용 : ");
if(pay > this.maxPay) { // 한도보다 금액이 높을 경우
System.out.print("한도초과! ");
}
else if(pay > account){ // 계좌금액보다 금액이 높을 경우
System.out.print("잔액부족! ");
}
else { // 둘 다 해당이 안되면
account -= pay;
}
System.out.println("남은 금액 " + account);
// 남은 금액을 출력하는 공통로직이 눈에 보이면 묶어주기 >> 모듈화
// 모듈화 : 동일한 기능을 하나의 함수로 묶는 것
}
}
public class Test07 {
public static void main(String[] args) {
// 홍길동씨는 최초에 20만원 보유
Card card1 = new Card("홍길동");
Card card2 = new Card("홍길동", 20000);
Card.account = 200000;
// 위처럼 사용하는 방법이 정확한 사용 방법이다.
card1.use(); // 10000원 사용 : 남은 금액 190000원
card1.use(100000); // 100000원 사용 : 남은 금액 90000원
card2.use(50000); // 50000원 사용 : 한도초과! 남은 금액 90000원
card2.use(); // 10000원 사용 : 남은 금액 80000원
card1.use(90000); // 90000원 사용 : 한도초과! 남은 금액 80000원
System.out.println();
card1.showInfo(); // 홍길동님[남은 금액 : 80000원]
card2.showInfo(); // 홍길동님[남은 금액 : 80000원]
}
}
----강사님 풀이
static, 생성자 오버로딩, 메서드 오버로딩을 잘 이용할 수 있는지에 대한 것
package class04;
class Card{
String name;
int limit;
static int bal;
void use() {
this.use(10000);
}
void use(int money) {
System.out.print(money+"원 사용: ");
if(money>this.limit) {
System.out.print("한도초과!");
}
else if(bal-money<0) {
System.out.print("잔액부족!");
}
else {
bal-=money;
}
System.out.println(" 남은 금액 "+bal+"원");
}
// 모듈화: 동일한 기능을 하나의 함수로 묶는 것
void showInfo() {
System.out.println(name+"님[남은금액: "+bal+"원]");
}
Card(String name){
this(name,200000);
}
Card(String name,int limit){
this.name=name;
this.limit=limit;
}
}
public class Test07 {
public static void main(String[] args) {
// 홍길동씨는 최초에 20만원 보유
Card card1=new Card("홍길동");
Card card2=new Card("홍길동",20000);
card1.bal=200000;
card1.use(); // 10000원 사용: 남은 금액 190000원
card1.use(100000); // 100000원 사용: 남은 금액 90000원
card2.use(50000); // 50000원 사용: 한도초과! 남은 금액 90000원
card2.use(); // 10000원 사용: 남은 금액 80000원
card1.use(90000); // 90000원 사용: 잔액부족! 남은 금액 80000원
card1.showInfo(); // 홍길동님[남은금액: 80000원]
card2.showInfo(); // 홍길동님[남은금액: 80000원]
}
}
System.out.println();
>> 클래스 변수다
System안에 out이라는 클래스변수다.
- this.는 객체인데 static은 모두가 공유하는 것이라서
this.account는 잘 사용하지 않는다.
=> 잘못된 것은 아니다.
this.use(10000)를 쓰게되는 상황
>> 예시로 설명
ex ) 가위바위보(앱에서 종종 나온다)
void 승부(가위){
가위를 화면에 띄우는 작업
}
void 승부(바위){
바위를 화면에 띄우는 작업
}
void 승부(보){
보를 화면에 띄우는 작업
}
-------------
모래성 게임 -- 강사님 작성
package class04;
import java.util.Random;
class Person{
String name;
static int sand=100;
boolean game() {
Random random = new Random();
int num=random.nextInt(20)+1;
System.out.println(name+"님이 "+num+" 가져갑니다..");
sand-=num;
System.out.println("남은 모래: "+sand);
System.out.println();
if(sand<=0) {
System.out.println(name+"님, 게임오버!");
return true;
}
return false;
}
Person(String name){
this.name=name;
}
}
public class Test08 {
public static void main(String[] args) {
Person p1=new Person("홍길동");
Person p2=new Person("아리");
Person p3=new Person("티모");
while(true) {
if(p1.game()) {
break;
}
if(p2.game()) {
break;
}
if(p3.game()) {
break;
}
}
}
}
배열을 이용한 방법
package class04;
import java.util.Random;
class Person {
String name;
static int sand = 100; // 공유 자원 sand 클래스변수!
boolean game() { // 메인쪽에서 승패를 받아야하기 때문에 return boolean
Random random = new Random();
int num = random.nextInt(20) + 1;
System.out.println(name + "님이" + num + " 가져갑니다..");
sand -= num;
System.out.println("남은 모래 : " + sand);
if(sand <= 0) {
System.out.println(name + "님 ,게임오버!");
return true;
}
return false;
}
Person(String name){
this.name = name;
}
}
public class Test08 {
public static void main(String[] args) {
// 배열이 필요하다
// 1. 자료형이 같아야 한다
// 2. 관련된 데이터여야 한다
// 3. 개수가 같아야 한다
// 객체 배열이 필요한 순간이다.
Person[] p = new Person[3];
p[0] = new Person("홍길동");
p[1] = new Person("아리");
p[2] = new Person("티모");
int i = 0;
while(true) {
if(p[i].game()) { // for문을 표현
break;
}
i++;
if(i==p.length) {
i=0;
}
}
}
}
-------------------
ex )
5 : 5
6 : 6
1시간짜리 문제(복습할 문제)
-강사님이 준비한 문제
학생부프로그램
학생 3명까지밖에 못들어옴
3명, 학생 -> 배열 사용하면 된다
비즈니스 메서드
CRUD
핵심 로직(메서드)
1. 추가 C
2. 출력 R
3. 정보 변경 U
(4. 삭제 D // 원래 있어야하는데 로직이 어려워 생략)
5. 종료
package class04;
import java.util.Scanner;
class Student{
String name;
int score;
void showInfo() {
System.out.println(name + "학생은 " + score + "점입니다.");
System.out.println();
}
Student(String name, int score){
this.name = name;
this.score = score;
System.out.println(this.name + "학생 입력완료!");
System.out.println();
}
}
public class Test09 {
public static void main(String[] args) {
Student[] data = new Student[3];
int index = 0; // 저장
Scanner sc = new Scanner(System.in) ;
while(true) {
System.out.println("1. 추가");
System.out.println("2. 출력");
System.out.println("3. 변경");
System.out.println("4. 종료");
System.out.print("입력 > ");
int act = sc.nextInt();
// 사용자가 입력하면 -> 유효성 검사!
if(act == 1) { // 추가 => 유효성 검사 + 인덱스 체크
if(index == data.length) {
System.out.println("데이터공간이 부족합니다.");
continue;
}
System.out.print("학생 이름 입력 : ");
String name = sc.next();
System.out.print("학생 성적 입력 : "); // 0부터 100까지
int score = sc.nextInt();
data[index] = new Student(name, score); // 객체를 만들기만 하고 초기화는 안했다.
index++;
}
else if(act == 2) { // 출력
if(index == 0) { // 인덱스가 0 하나도 안 차 있으면
System.out.println("저장한 정보가 없습니다");
continue;
}
System.out.println("===학생 목록===");
for(int i = 0; i < index; i++) {
data[i].showInfo();
}
}
else if(act == 3) { // 변경
System.out.print("정보를 변경할 학생의 번호 입력 : ");
int num = sc.nextInt();
num--; // 번호와 인덱스 넘버의 차이
if(num < 0 || index <= num) {
System.out.println("없는 번호입니다! 확인 후 다시 이용해주세요~~");
System.out.println();
continue;
}
System.out.print("변경할 점수 입력 : ");
data[num].score=sc.nextInt();
System.out.println(data[num].name + "학생 변경완료");
System.out.println();
}
else if(act == 4) { // 종료
System.out.println("종료됩니다...");
break;
}
else { // 이외의 숫자를 입력 시
System.out.println("잘못된 입력입니다.");
}
}
}
}
'디바이스 융합 자바(Java)기반 풀스택 개발자 양성과정(수업내용)' 카테고리의 다른 글
디바이스 융합 자바(Java) day11 - toString,instanceof,포켓몬 (0) | 2022.06.21 |
---|---|
디바이스 융합 자바(Java) day10 - 학생부(삭제),접근제어자,상속,super(부모의 생성자 호출),상수,오버라이딩 (0) | 2022.06.20 |
디바이스 융합 자바(Java) day07 - 함수 모듈화,객체지향 프로그래밍,오버로딩,this. (0) | 2022.06.15 |
디바이스 융합 자바(Java) day06 - 함수,오버로딩 (0) | 2022.06.14 |
디바이스 융합 자바(Java) day05 - 버블정렬,최대값 찾기,이진검색,배열 이진검색,flag 변수 (0) | 2022.06.13 |