🧐 지난 블로깅에 이어 다시 보는 java 동작 과정(그림)
public class MyProfile {
private int age;
public double tall = 180.5;
public char gender = '남';
public boolean isPretty= true;
public String name = new String("김철수");
public Date birthday = new Date(2000, 1, 1);
public static void main(String[] args) {
MyProfile m = new MyProfile();
System.out.println(m.age);
System.out.println(m.tall);
System.out.println(m.gender);
System.out.println(m.isPretty);
System.out.println(m.name.toString());
System.out.println(m.birthday.getYear() + "년 " + m.birthday.getMonth() + 1 + "월 " + m.birthday.getDate() + "일");
}

Java 타입 캐스팅
- 레지스터에서 수행
Widening Casting
작은 타입에서 큰 타입으로 변환
public class Main {
public static void main(String[] args) {
int myInt = 9;
double myDouble = myInt; // 자동 변환
System.out.println(myInt); // 9
System.out.println(myDouble); // 9.0
}
}
Narrowing Casting
큰 타입에서 작은 타입으로 변환
public class Main {
public static void main(String[] args) {
double myDouble = 9.78d;
int myInt = (int) myDouble;
System.out.println(myDouble); // 9.78
System.out.println(myInt); // 9
}
}
Java 문자열
🌟 Reference data
원칙: new 생성자();
예외: String은 new 없이 문자열 만으로도 표현 가능 ⬅️ 시간 및 공간 복잡도를 줄이기 위함
- double quotation(")을 만나면 string literal pool에서 처리
package com.kse.basic;
public class StringTest {
public static void main(String[] args) {
String s1 = new String("java");
String s2 = new String("java");
String s3 = "java";
String s4 = "java";
System.out.println(s1);
System.out.println(s2);
System.out.println(s1 == s2); // false
System.out.println(s3);
System.out.println(s4);
System.out.println(s3 == s4); // true
s3 = "wava";
System.out.println(s3); // wava
System.out.println(s4); // java
System.out.println(s3 == s4); // false
String s5 = s4.concat(s3);
System.out.println(s3); // wava
System.out.println(s4); // java
System.out.println(s5); // javawava
}
}

🌟 동시성 문제?
String 객체는 같은 주소를 공유하는 데 하나의 값이 변한다면?
➡️ String은 불변 객체! 기존 객체가 변하는 것이 아니라 새로운 객체를 생성

🌟 concat 메서드 수행
- instance 공간에 새로운 객체 생성

🌟 for문을 통한 String 값 변화
- 시간 복잡도, 공간복잡도 증가

➡️ 해결: StringBuffer / StringBuilder
package com.kse.basic;
public class StringTest2 {
public static void main(String[] args) {
String s1 = "java";
StringBuffer s2 = new StringBuffer("java");
StringBuffer s3 = new StringBuffer(100);
StringBuilder s4 = new StringBuilder(100);
s4.append("java");
for(int i = 0; i < 5; i++) {
s1 += i; // StringBuffer & StringBuilder 에서는 연산자 사용 하지 않기, append 메서드 쓰기
s2.append(i);
System.out.println(s);
}
}
}

- 동시성 문제가 생길 수 없는 곳에 StringBuilder 사용! StringBuilder는 Rock 시스템이 없기 때문!
- 또한, StringBuffer/StringBuilder 사용 시 +/-와 같은 연산자 사용 X !!
- 다시 문자열로 변환되는 과정을 거쳐야 함
Java Methods
- 메서드 안에 또 다시 메서드 정의 불가능, 무조건 class 내 위치
- 메서드는 return이 생략되어 있어도 무조건 가지고 있음(종료 brace 만나면 종료됨)
- return을 안 쓸 경우 void로 메서드 선언해야 함
- static 키워드를 사용하면 객체 생성 없이 타 메서드 사용 가능
- 단, 최소화하여 사용해야 함 ⬅️ Garbage Collector가 돌아가지 않음, 서버가 종료되기 전까지 계속 남아있음(Perm Gen)
- data - 공유하는 데이터일 때 static 사용
- methods
- instruction을 로드하는 시점에 static 메서드가 올라감
- 객체 지향은 instance 영역을 탄력적으로 쓰기 위한 것이기 때문에 코드 설계 시 static을 남용하는 것은 좋지 않음 !
package com.kse.basic;
public class MethodTest {
public static void main(String[] args) {
MethodTest m = new MethodTest();
m.a();
b();
}
void a() { // static 키워드가 없으면 찾지 못함 -> 메모리를 생성자를 통해 잡아줘야 함
System.out.println("a 호출");
}
static void b() { // usage modifier: 객체 생성 없이 사용 가능
System.out.println("b 호출");
}
}
메서드 오버로딩
- 메서드들의 기능이 같다면 메서드 이름은 같도록 정의
- 단, 파라미터는 타입 또는 개수가 달라야 함
- 리턴 타입은 상관 없음
package com.kse.basic;
public class MethodTest {
public static void main(String[] args) {
MethodTest m = new MethodTest();
m.print(1);
m.print(10.0);
}
// 메서드 오버로딩
void print(int i) {
System.out.println("i 호출");
}
void print(double d) {
System.out.println("d 호출");
}
}
재귀

Java 클래스
클래스: 프로그램 단위(코드)
객체: 메모리 정보(수행 결과)
OOP 3대 기법
1. encapsulation(은닉화)
- 데이터 보호
- 방법: data는 private으로, method는 4가지 중 하나로 적절히 선언

2. inheritance(상속)
- 단일 상속: extends Super
package com.kse.basic;
public class InheritanceTest {
public static void main(String[] args) {
InheritanceTest t = new InheritanceTest();
String s = t.toString(); // 주소값 리턴
int i = t.hashCode(); // 유일값 리턴
System.out.println(s);
System.out.println(i);
InheritanceTest t2 = new InheritanceTest();
boolean b= t.equals(t2); // 주소값 비교
System.out.println(t == t2);
System.out.println(b);
}
}
3. polymorphizm(다형성)
다음 게시글에서 계속...
Java 배열
- 대괄호([])를 변수 유형으로 지정
String[] cars;
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"}; // 초기화
- 배열의 길이는 length 속성 활용
String[] cars = {"Volvo", "BMW", "Ford", "Mazda"};
System.out.println(cars.length);
- 다차원 배열
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
- 반복문 활용
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
for (int i = 0; i < myNumbers.length; ++i) {
for (int j = 0; j < myNumbers[i].length; ++j) {
System.out.println(myNumbers[i][j]);
}
}
// for-each 루프로 표현
int[][] myNumbers = { {1, 2, 3, 4}, {5, 6, 7} };
for (int[] row : myNumbers) {
for (int i : row) {
System.out.println(i);
}
}
알고리즘 스터디
📍 프로그래머스 배열 문제 풀기
문제1: 배열 길이에 따라 다른 연산하기
조건문과 반복문을 적절히 활용하여 쉽게 구현하였다.
class Solution {
public int[] solution(int[] arr, int n) {
if(arr.length%2!=0){
for(int i=0;i<arr.length;i+=2){
arr[i]+=n;
}
}else{
for(int i=1;i<arr.length;i+=2){
arr[i]+=n;
}
}
return arr;
}
}
문제2: 배열 비교하기
조건문을 중첩하여 풀었는데 다른 사람들이 푼 코드를 보니 4줄이면 끝난 코드가 있었다. 다들 java의 Stream을 이용하는 것 같은데 아직 배우지 못해서 코드가 길더라도 중첩 조건문을 사용했다.
class Solution {
public int solution(int[] arr1, int[] arr2) {
if(arr1.length<arr2.length){
return -1;
}else if(arr1.length>arr2.length){
return 1;
}else{
int sum1=0;
int sum2=0;
for (int a:arr1 ){
sum1+=a;
}
for (int a:arr2 ){
sum2+=a;
}
if(sum1<sum2){
return -1;
}else if(sum1>sum2){
return 1;
}else{
return 0;
}
}
}
}
문제3: 배열의 평균값
간단하게 평균을 구하면 되는 문제였고 여기서 타입 캐스팅을 썼다!
테스트 시, 정수로 출력된 것을 발견하고 (double)을 써야할 것 같다고 제안했다.
class Solution {
public double solution(int[] numbers) {
int sum=0;
double avg=0;
for(int i=0;i<numbers.length;i++){
sum+=numbers[i];
}
avg=(double)sum/numbers.length;
return avg;
}
}
문제4: 배열 원소의 길이
특정 길이로 배열을 초기화하는 법을 몰라서 찾아봤다. new int[길이]로 쓰면 된다는 것을 확인하고 배열 원소의 길이를 출력할 수 있게끔 했다.
class Solution {
public int[] solution(String[] strlist) {
int[] answer = new int[strlist.length];
for(int i=0;i<strlist.length;i++){
answer[i]=strlist[i].length();
}
return answer;
}
}
문제5: 배열의 유사도
처음에는 문자열을 s1[i] == s2[i]로 비교했었는데 생각해보니 주소값을 비교하는 것이기 때문에 당연히 다르게 나올 수 밖에 없음을 깨달았다. 그래서 toString() 메서드를 활용했는데 이것도 아니였고..
찾아본 결과 equals 메서드 사용하기!!
a.equals(b)로 작성하면 두 문자열이 같은 지 비교할 수 있다.
class Solution {
public int solution(String[] s1, String[] s2) {
int answer = 0;
for(int i=0; i<s1.length; i++) {
for(int j=0; j<s2.length; j++) {
if(s1[i].equals(s2[j])) {
answer++;
}
}
}
return answer;
}
}
문제6: 배열 자르기
여기서 조금 머리가 꼬였는데 일단 자를 배열의 길이만큼 초기화해 리턴할 배열을 만들어줬다.
그런 다음 파라미터로 받은 배열을 특정 인덱스부터 순회하며 값을 집어 넣어 해결했다.
class Solution {
public int[] solution(int[] numbers, int num1, int num2) {
int[] answer = new int[num2-num1+1];
int index=0;
for(int i=num1;i<=num2;i++){
answer[index]=numbers[i];
index++;
}
return answer;
}
}
❕느낀점: 같이 하는 스터디원 모두 자바와 알고리즘에 대해서 아직은 잘 모르기 때문에 문제 푸는 속도가 더디긴 하지만 각자의 머리에서 나오는 것들을 모아 해결하니 혼자 풀 때보다 더 재밌는 것 같다 !
'LG 유플러스 유레카 SW > Java' 카테고리의 다른 글
[#14] Java 재귀 & 배열 & Exception (0) | 2025.02.13 |
---|---|
[#13] Java Generic & Collection (0) | 2025.02.12 |
[#12] Java 코드 성능 & 가독성 높이는 법 (0) | 2025.02.11 |
[#11] Java 다형성 + Class 다이어그램 그려보기 (0) | 2025.02.10 |
[#9] Java 들어가기 전에.. (0) | 2025.02.06 |