생성자
1.메모리를 할당 받을 때 사용
2.변수 초기화 목적
클래스의 이름과 동일
리턴값이 없기 때문에 property가 없다. 생성자냐 메소드냐 둘중에 하나.
property가 있다면 무조건 메소드
오버로딩이 가능함. (오버로딩 : 메소드중복정의. 하나의 클래스 안에서 이름은 같지만 데이터 자료형,매개변수 갯수 상이함.)
코딩의 첫째줄에서 한번만 호출 가능 <- 상속에서 추가설명
public class Test1 {
//instance 변수와 초기화 메소드는 세트라고 생각. 없으면 초기값 설정할 수 없음.
private int x; //instance변수
//생성자코딩. 변수선언한 끝에 있음. void, int 등 리턴값 없음.
public Test1(){ //기본생성자. 무조건 작성되어지고 표기가 생략되어 있음. 중복정의(오버로딩) 할거 아니라면 생략
this(100); //오버로딩된 생성자를 호출. 사용하려면 맨앞줄에 한번만 써줘야 오류안남
System.out.println("기본생성자(인수가 없는 생성자)");
x=10; //생성자를 통한 변수초기화
System.out.println("x: "+ x);
}
/*
public Test1(){}
기본생성자를 지워버리면 무조건 오버로딩된 생성자로 생성.
Database활용시 기본생성자에 저장경로를 세팅해놔서 객체생성과 동시에 위치 설정을 하면 손쉽게 관리 가능
반드시 필요한 변수값 설정시 사용
*/
public Test1(int x){//필요에 의해 만드는 오버로딩된 생성자
//this(); // 오버로딩된 생성자에서 기본생성자 호출가능. 지금은 기본생성자 호출. 사용하려면 맨앞줄에 한번만 써줘야 오류안남
System.out.println("중복정의된 생성자");
this.x = x;
System.out.println("x: "+ x);
}
public void set(int x){ //초기화메소드
this.x = x;
}
//생성자를 통한 변수초기화 : public Test1() 가
//초기화메소드: set() 를 이용한 초기화보다 빠르다!
public static void main(String[] args) {
Test1 ob1 = new Test1(); //객체 생성을 통해 메모리를 할당받고 public Test1()로 가서 실행해줌. 기본생성자 호출
ob1.set(10);
System.out.println("main ob1.x: " + ob1.x);
Test1 ob2 = new Test1(20); //오버로딩된 생성자 호출. 객체 생성과 동시에 초기화 진행
//오버로딩된 생성자를 사용하기 위해서는 반드시 기본생성자도 같이 정의해줘야 함
//이 때, 기본생성자를 정의하지 않는다면 사용이 불가능.
//중복정의해서 사용하는 게 자주 있진 않지만, 필요할 수 있으니 기억.
}
}
private 변수 초기화 방법은 두가지. 초기화메소드 이용, 생성자 이용
class Rect{
private int w;
private int h;
public Rect(){//기본생성자
}
public Rect(int w, int h){//오버로딩된 생성자
this.w = w;
this.h = h;
}
public void set(int w, int h){//초기화 메소드
this.w = w;
this.h = h;
}
public int area(){
return w*h;
}
public int length(){
return 2*(w+h);
}
public void print(int a, int l){
System.out.println("가로: "+ w);
System.out.println("세로: "+ h);
System.out.println("넓이: "+ a);
System.out.println("둘레: "+ l);
}
public void print(int a){ //메소드 오버로딩(중복정의)
System.out.println("가로: "+ w);
System.out.println("세로: "+ h);
System.out.println("넓이: "+ a);
}
}
public class Test2 {
public static void main(String[] args) {
Rect ob1 = new Rect(); //기본생성자 + 초기화메소드 사용
ob1.set(10, 20);
int area = ob1.area();
int length = ob1.length();
ob1.print(area);
ob1.print(area, length);
System.out.println("-------------------");
Rect ob2 = new Rect(100,200); //오버로딩된 생성자를 통해 객체 생성시 초기화 바로 진행. spring에서 '의존성 주입'이라고 함
area = ob2.area();
length = ob2.length();
ob2.print(area);
ob2.print(area, length);
}
}
객체가 생성되면 바로 실행되는 instance 블럭
public class Test3 {
int a=5; //instance변수
{//초기화 블럭. 메소드로 호출하진 않는데 형식은 갖춰야 함. instance. 객체를 생성해야 볼 수 있음
System.out.println("초기화 블럭 a -> " + a);
a=10;
System.out.println("초기화 블럭 a -> " + a);
}
static int b; //클래스변수. 메모리 할당 되어 있음.
static{//static 블럭
b = 20;
System.out.println("static 블럭 b -> " + b);
}
final int C; //final변수 = 상수. 항상 변하지 않는 수. 대문자로 작성함. 프로그램이 끝날 때 까지 값을 바꿀 수 없음
//은행에서의 변동하지 않는 고정이자율. 원주율(파이)와 같은 변수 설정시 사용한다.
//상수에 값을 설정 안해두면 에러. 초기값 반드시 설정해야 함. 메모리에 올라가야만 초기화 가능.
//일반 메소드에서 초기화 시킬 수 없음
public Test3(){
System.out.println("생성자...");
C = 100;
System.out.println("C:"+ C);
}//이런 경우에 가장 마지막에 생성되는 것은 생성자.
public static void main(String[] args) {
Test3 ob = new Test3(); //객체생성. static블록이 제일 먼저 생성됨
Test3 ob1 = new Test3(); //객체 두개 생성시 static은 객체를 여러번 만들어도 한번만 만들어진다. 메모리를 같이 쓰니까
final int k = 10;
}
}
되부름 함수(재귀함수)
장점 : 소스가 간단해짐. 소스가 짧음
단점 : 처리속도가 느림(stack에 저장했다가 출력하기 때문에)
비정형인수 예제
public class Test4 {
public void print(int n){
if(n!=1){
print(n-1); //되부름함수, 메소드안에서 함수호출시 자기 자신을 부름
}
System.out.printf("%5d",n);
}
public int sum(int n){
//1-10까지의 합
return n>1 ? n+sum(n-1) : n;
}
public int pow(int a , int b){
return b>=1 ? a*pow(a,b-1) : 1;//메소드안에서 자기자신 호출 = 되부름함수
}
//비정형인수
int sum(int...args){
int sum=0;
/*
for(int i=0;i<args.length;i++){
sum+=args[i];
}
*/
for(int su: args){ //확장for문으로도 사용가능
sum += su;
}
return sum;
}
public static void main(String[] args) {
Test4 ob = new Test4();
ob.print(5);
System.out.println();
int s = ob.sum(100);
System.out.println(s);
System.out.println("pow(2,10): " + ob.pow(2,10));
//비정형인수
int result;
result = ob.sum(2,4,6,8,10); //배열 설정시에는 크기를 지정해야 되는데 비정형인수는 정해져 있지않아도 배열처럼 연산가능
System.out.println(result);
result = ob.sum(1,3,5,7,9,11,13,15,17);
System.out.println(result);
}
}
클래스를 활용하여 객체 생성 후 계산기 만들기
import java.io.IOException;
import java.util.Scanner;
class Calc{
private int num1, num2;
private char oper;
public boolean input() throws IOException{
Scanner sc = new Scanner(System.in);
System.out.print("두개의 수?");//10 20
num1 = sc.nextInt();
num2 = sc.nextInt();
System.out.println("연산자?");//+,-,*,/
oper = (char)System.in.read();
if(oper!='+' && oper!='-' && oper!='/' && oper!='*'){
return false;
}
return true;
}
public int result(){
int r = 0;
switch(oper){
case '+':
r = num1 + num2; break;
case '-':
r = num1 - num2; break;
case '/':
r = num1 / num2; break;
case '*':
r = num1 * num2; break;
}
return r;
}
public void print(int r){
System.out.printf("%d %c %d = %d\n",num1, oper, num2, r);
}
}
public class Test5 {
public static void main(String[] args) throws IOException {
Calc ob = new Calc();
boolean b = false;
int r = 0 ;
/*
b = ob.input(); //예외처리를 main문에서도 써줘야 함
if(b==true){
r = ob.result();
ob.print(r);
}
System.out.println("연산자 오류!!");
*/
//boolean이므로 True나 False값이 나옴. 일반적으로 중괄호 바깥을 정상실행의 경우로 작성. 소스코드가 길어서
if(!ob.input()){
System.out.println("연산자 오류!!");
return;
}
r = ob.result();
ob.print(r);
}
}
Call By Value.
동일 변수값을 가진다. stack 영역의 데이터가 Heap영역으로 데이터 자체가 넘어감
Call By Reference
Heap영역에 있는 데이터를 복사할때 데이터자체가 복사되는게 아니라 주소가 복사되는 것. static과 같은 역할을 함
동일 주소를 가진다. 주소를 서로 나누어 가짐. 이미 만들어진 것을 가져다 쓸 때 사용
class Test{
public int x= 10;
public void sub(int a){
x += a; //x=x+a
}
}
public class Test6 {
public static void main(String[] args) {
Test ob = new Test();
int a = 10;
System.out.println("sub메소드 실행전 :" + ob.x);
ob.sub(a);// Call by value
System.out.println("sub메소드 실행후 :" + ob.x);
Test ob1;
ob1 = ob; //Call by reference. ob의 주소값을 ob1에 넣어라. 주소값을 복사해서 같은 곳을 가리키므로 동일값 나옴
System.out.println("ob.x:" + ob.x ); //20
System.out.println("ob1.x:" + ob1.x ); //20
//똑같은 위치인 걸 어떻게 아느냐. 값을 변경해서 다시 조회해보면 됨
ob1.x = 100;
System.out.println("ob.x:" + ob.x ); //100
System.out.println("ob1.x:" + ob1.x ); //100
}
}
상속(부모가 자식한테 주는 것)
1. 부모꺼는 내거다
2. private 로 선언한 것은 상속이 불가능
3. protected 로 선언한 것은 상속이 가능. 같은 패키지안에서라면 사용 가능
4. 내꺼는 내거다. 부모가 가져다가 쓸 순 없음. 이순신의 특징은 이순신만 사용 가능!
5. 부모도 가지고 있고 나도 가지고 있으면 내꺼 쓴다.
class SuperClass{
private String title;
private int area;
public void set(String title, int area){
this.area=area;
this.title = title;
}
public void print(){
System.out.println(title + ":" + area);
}
}
class SubClass extends SuperClass{ //다중상속이 안되기 때문에 하나만 쓸수있음(단일상속)
private int w;
private int h;
public SubClass(int w, int h){ //생성자 초기화
this.w = w;
this.h = h;
}
public void rectArea(){
int a = w*h;
//area = w*h; 바로 area에 입력할 수 없음. private이기 때문 //2.private로 선언한 것은 상속이 불가능
set("사각형", a); //1.부모꺼는 내거다
}
}
public class Test7 {
public static void main(String[] args) {
SubClass ob = new SubClass(10,20);
ob.rectArea();
ob.print();//1.부모꺼는 내거다
}
}
상속(부모가 자식한테 주는 것)
1. 부모꺼는 내거다(자식도 그대로 쓸 수 있음)
2. private 로 선언한 것은 상속이 불가능
3. protected 로 선언한 것은 상속이 가능
4. 내꺼는 내거다. 부모가 가져다가 쓸 순 없음
5. 부모도 가지고 있고 나도 가지고 있으면 내꺼 쓴다.
class SuperClassA{
private String title;
protected int area; // 자식도 사용가능하도록 접근제어자 변경
public void set(String title){
this.title = title;
}
public void print(){
System.out.println(title + ":" + area);
}
}
class SubClassA extends SuperClassA{ //다중상속이 안되기 때문에 하나만 쓸수있음(단일상속)
private int w;
private int h;
public SubClassA(int w, int h){ //생성자 초기화
this.w = w;
this.h = h;
}
public void rectArea(){
//int a = w*h;
area = w*h; //3. protected 로 선언한 것은 상속이 가능
set("사각형"); //1.부모꺼는 내거다
}
}
public class Test8 {
public static void main(String[] args) {
SubClassA ob = new SubClassA(100,200);
ob.rectArea();
ob.print();//1.부모꺼는 내거다
ob.area = 10; //protected 일때는 접근 가능
System.out.println("area : "+ ob.area);
}
}
'Dev > Java' 카테고리의 다른 글
[java] Calendar 클래스, Wrapper 클래스, Singleton, final (0) | 2019.01.24 |
---|---|
[java] 상속, Object 클래스, String클래스, StringBuffer와 StringBuilder (0) | 2019.01.24 |
[java] static변수, 변수 초기화 방법, Overloading (0) | 2019.01.22 |
[java] 전역/지역변수, 버블정렬,구구단만들기 (0) | 2019.01.22 |
[java] 선택정렬, 난수, 가위바위보 게임만들기 (0) | 2019.01.22 |