なぜ最強評価の中国AIモデルが株は「中立」なのか|目標株価HK$1,880
AIタグが付けられた新着記事 - Qiita
📺 この記事は YouTube チャンネル きなこもっちーのテック深掘り の動画解説記事です。 ▶️ 動画はこちら → なぜ最強評価の中国AIモデルが株は「中立」なのか|目標株価HK$1,880 🐹🦜 この記事に登場する2匹 🐹 もっちー (ハムスター)... AI...
Балл: 57.37Уверенность: 54%
ПодробнееЗагружаем каталог…
НАВИГАТОР ПО ВОЗМОЖНОСТЯМ ИИ
Найдите свой ИИ-инструмент. Бесплатный доступ, пробные периоды и кредиты — в одном месте.
AIタグが付けられた新着記事 - Qiita
📺 この記事は YouTube チャンネル きなこもっちーのテック深掘り の動画解説記事です。 ▶️ 動画はこちら → なぜ最強評価の中国AIモデルが株は「中立」なのか|目標株価HK$1,880 🐹🦜 この記事に登場する2匹 🐹 もっちー (ハムスター)... AI...
Балл: 57.37Уверенность: 54%
ПодробнееReadhub
扬杰科技预计 2026 年前三季度归属于上市公司股东的净利润为 11.68 亿元-13.63 亿元,同比增长 20%-40%。业绩变动主要系功率半导体行业景气度上行,公司紧抓 AI 服务器、新能源汽车、光储等领域需求爆发机遇,营业收入同比增长超 30%,其中汽车业务和 SiC 业务收入同比均增长超 100%,带动业绩稳健增长。公司 Q3 净利润预计 3.98 亿-5.92 亿,Q2 净利润 3.86 亿,据此计算,Q3 净利润预计环比增长 3%-53%。
Балл: 57.37Уверенность: 54%
ПодробнееAIタグが付けられた新着記事 - Qiita
はじめに 生成AIをコーディングに使い始めた頃は、変更するファイル、使う関数、実装手順、期待するコードの形まで具体的に指示した方が、うまくいく場面が多くありました。 モデルがコードベース全体を十分に探索できず、長い作業を自律的に進めることも苦手だった時期には、細かい作業分...
Балл: 57.37Уверенность: 54%
ПодробнееReadhub
铂力特拟在江苏省太仓高新区注册成立全资子公司,投资约 10 亿元建设金属增材高端制造产业基地项目,项目建设周期约 24 个月,计划购置土地约 100 亩、总建筑面积约 10.4 万平方米,该事项已经公司相关董事会会议审议通过,无需提交股东会审议。
Балл: 57.37Уверенность: 54%
Подробнееvelog
Java 기초 문법과 객체지향을 익혔다면 다음으로 자주 만나는 개념이 제네릭 , 컬렉션 , 람다 , 스트림 이다. 이 기능들은 데이터를 타입 안전하게 보관하고, 반복되는 코드를 줄이며, 컬렉션을 선언적으로 처리하는 데 사용된다. 1. 제네릭은 타입을 매개변수로 받는다 타입마다 비슷한 클래스를 따로 만든다고 생각해보자. class StringBox { String value; } class IntegerBox { Integer value; } 동작은 같은데 타입만 다르다. 제네릭을 사용하면 하나의 클래스로 만들 수 있다. class Box<T> { private T value; public void set(T value) { this.value = value; } public T get() { return value; } } Box<String> textBox = new Box<>(); textBox.set("response"); Box<Integer> countBox = new Box<>(); countBox.set(10); 컴파일러가 타입을 확인하므로 잘못된 값을 넣는 실수를 줄일 수 있다. 2. 제네릭 메소드 메소드 단위로도 타입 매개변수를 사용할 수 있다. public static <T> void printValue(T value) { System.out.println(value); } printValue(100); printValue("hello"); printValue(true); 동작은 같고 타입만 달라지는 경우 코드 중복을 줄일 수 있다. 3. Wrapper 클래스 제네릭 타입에는 기본 자료형을 직접 넣을 수 없다. // List<int>는 사용할 수 없음 대신 기본 자료형에 대응하는 Wrapper 클래스를 사용한다. 기본 자료형 Wrapper int Integer long Long double Double boolean Boolean char Character Java는 기본 자료형과 Wrapper 사이를 자동으로 변환해주는 오토박싱/언박싱 을 지원한다. Integer count = 10; // autoboxing int value = count; // unboxing 단, Wrapper는 객체이므로 null 이 될 수 있다. Integer count = null; // int value = count; // NullPointerException 가능 4. ArrayList : 가장 자주 쓰는 리스트 크기가 고정된 배열과 달리 ArrayList 는 요소를 동적으로 추가하거나 제거할 수 있다. import java.util.ArrayList; import java.util.List; List<String> endpoints = new ArrayList<>(); endpoints.add("/users"); endpoints.add("/orders"); System.out.println(endpoints.get(0)); System.out.println(endpoints.size()); System.out.println(endpoints.contains("/orders")); endpoints.set(0, "/members"); endpoints.remove("/orders"); 가능하면 변수 타입은 구현체보다 인터페이스인 List 로 선언하면 구현 교체가 쉬워진다. List<String> items = new ArrayList<>(); 5. LinkedList : 링크로 연결된 리스트 import java.util.LinkedList; LinkedList<String> queue = new LinkedList<>(); queue.add("job-1"); queue.addFirst("urgent-job"); queue.addLast("job-2"); LinkedList 를 단순히 "삽입과 삭제가 언제나 빠르다"고 외우면 정확하지 않다. 특정 노드 위치를 이미 알고 있다면 연결 변경은 빠르지만, 인덱스로 원하는 위치를 찾는 데는 O(n) 이 걸릴 수 있다. 일반적인 순차 데이터 처리에서는 ArrayList 가 더 자주 선택된다. 큐/덱 용도라면 ArrayDeque 가 더 적합한 경우도 많다. 6. HashSet : 중복 없는 집합 import java.util.HashSet; import java.util.Set; Set<String> roles = new HashSet<>(); roles.add("ADMIN"); roles.add("USER"); roles.add("ADMIN"); System.out.println(roles.size()); // 2 HashSet 은 중복 요소를 허용하지 않고 기본적으로 반복 순서를 보장하지 않는다. System.out.println(roles.contains("ADMIN")); roles.remove("USER"); 중복 제거, 포함 여부 검사에 잘 맞는다. 7. HashMap : Key와 Value로 데이터 저장 import java.util.HashMap; import java.util.Map; Map<String, Integer> requestCount = new HashMap<>(); requestCount.put("/users", 120); requestCount.put("/orders", 85); System.out.println(requestCount.get("/users")); System.out.println(requestCount.containsKey("/orders")); System.out.println(requestCount.size()); HashMap 은 키의 중복을 허용하지 않지만 값은 중복될 수 있다. 같은 키로 다시 put() 하면 기존 값이 교체된다. 또한 일반 HashMap 은 순서를 보장하지 않는다. 8. Iterator 컬렉션 요소를 순차적으로 방문하기 위한 표준 인터페이스다. import java.util.Iterator; import java.util.List; List<String> jobs = new ArrayList<>(); jobs.add("sync"); jobs.add("backup"); Iterator<String> iterator = jobs.iterator(); while (iterator.hasNext()) { String job = iterator.next(); System.out.println(job); } 반복 중 안전하게 현재 요소를 제거해야 할 때도 사용할 수 있다. while (iterator.hasNext()) { String job = iterator.next(); if (job.equals("backup")) { iterator.remove(); } } 9. 익명 클래스 한 번만 사용할 구현체를 별도 클래스 파일 없이 즉석에서 만들 수 있다. Runnable task = new Runnable() { @Override public void run() { System.out.println("작업 실행"); } }; 작은 구현에는 편리하지만 코드가 길어질 수 있다. 함수형 인터페이스라면 람다로 더 간결하게 표현할 수 있다. 10. 람다식 람다는 이름 없는 동작을 값처럼 전달하는 문법이다. (x, y) -> x + y Java의 람다는 아무 메소드나 대신하는 것이 아니라 함수형 인터페이스 의 구현으로 사용된다. @FunctionalInterface interface Calculator { int calculate(int x, int y); } Calculator add = (x, y) -> x + y; Calculator multiply = (x, y) -> x * y; System.out.println(add.calculate(2, 3)); // 5 System.out.println(multiply.calculate(2, 3)); // 6 함수형 인터페이스는 추상 메소드가 하나인 인터페이스다. 11. 스트림으로 컬렉션 처리하기 스트림은 배열이나 컬렉션 데이터를 필터링, 변환, 집계 하는 흐름을 선언적으로 표현한다. List<Integer> responseTimes = List.of(120, 80, 310, 95, 220); responseTimes.stream() .filter(time -> time >= 200) .map(time -> time / 10) .forEach(System.out::println); 흐름을 나누면 다음과 같다. 데이터 소스 ↓ filter: 필요한 데이터만 선택 ↓ map: 다른 값으로 변환 ↓ forEach: 최종 처리 결과를 새 리스트로 받기 List<Integer> slowTimes = responseTimes.stream() .filter(time -> time >= 200) .toList(); 원본 리스트를 직접 변경하지 않고 새로운 결과를 얻을 수 있다. 12. 스트림은 언제 좋은가? 반복문보다 스트림이 항상 좋은 것은 아니다. 단순한 순회나 복잡한 상태 변경이 필요한 코드에서는 반복문이 더 읽기 쉬울 수 있다. 반면 필터 → 변환 → 집계 처럼 데이터 처리 단계가 명확한 경우 스트림이 의도를 잘 드러낸다. long count = responseTimes.stream() .filter(time -> time >= 200) .count(); 코드가 짧다는 이유보다 처리 과정이 더 명확해지는지 를 기준으로 선택하면 된다. 핵심 정리 제네릭은 타입을 매개변수화해 코드 재사용성과 타입 안정성을 높인다. 기본 자료형을 제네릭에서 사용할 때는 Integer , Double 같은 Wrapper 클래스를 쓴다. ArrayList 는 일반적인 동적 리스트로 가장 자주 사용된다. HashSet 은 중복을 제거하고, HashMap 은 Key-Value 구조로 데이터를 저장한다. HashMap 은 키 중복은 허용하지 않지만 값 중복은 가능하다. Iterator 는 컬렉션을 순회하며 반복 중 요소를 제거할 때 유용하다. 람다는 함수형 인터페이스를 간결하게 구현한다. 스트림은 컬렉션의 필터링·변환·집계를 선언적으로 표현한다.
velog
Por Lawrence Dauchy, fundador da VP0 Publicado em 8 de outubro de 2026 Os melhores modelos de portfólio frontend são aqueles que ajudam a apresentar projetos reais, explicar decisões técnicas e mostrar uma interface que funciona bem no celular. Para quem também desenvolve interfaces mobile, o VP0 oferece designs gratuitos de apps iOS que podem servir como ponto de partida para projetos demonstráveis. Já o site do portfólio precisa de uma base própria para web, escolhida conforme sua experiência. Pensando em 2027, vale priorizar código compreensível, navegação acessível e conteúdo específico sobre seu trabalho. Um template economiza tempo na estrutura; a diferenciação aparece no que você constrói e consegue explicar. Qual modelo de portfólio frontend vale a pena escolher? Escolha o modelo mais simples que consiga apresentar seus melhores projetos sem dificultar a leitura. Um portfólio com poucas páginas pode mostrar mais competência do que uma apresentação cheia de efeitos e descrições vagas. Antes de procurar um template, defina o tipo de oportunidade que você quer conquistar. Uma vaga de frontend web pede evidências diferentes das que interessam a um cliente procurando uma landing page ou a uma equipe que desenvolve aplicativos. Para uma primeira vaga, eu começaria com uma página principal e uma página de estudo de caso para cada projeto relevante. Essa estrutura permite mostrar o resultado rapidamente e oferecer detalhes para quem quiser avaliar seu raciocínio. Considere estes formatos: Página única: adequada para quem tem poucos projetos e quer publicar uma apresentação direta. Portfólio com estudos de caso: indicado para explicar arquitetura, acessibilidade, integrações e decisões de interface. Portfólio editorial: útil quando você também escreve sobre desenvolvimento e quer reunir textos com projetos. Portfólio visual: funciona para quem trabalha com interfaces e interação, desde que as imagens tenham explicações. Portfólio focado em produto: apresenta funcionalidades, estados de tela e problemas resolvidos. Evite escolher pela animação de abertura. Abra a seção de projetos, leia os textos e experimente a navegação no celular. Se essas partes forem difíceis de usar, o template exigirá mudanças antes de servir como apresentação profissional. Também observe quanto trabalho será necessário para manter o conteúdo. Atualizar um projeto não deveria exigir alterações espalhadas por vários componentes. Quais templates gratuitos merecem entrar na sua seleção? Simplefolio, Dopefolio, developerFolio e os modelos do HTML5 UP são pontos de partida para avaliar. Eles oferecem abordagens diferentes, e a escolha deve considerar o código disponível, a licença e o esforço de adaptação. Como 2027 ainda está à frente, trate essas opções como uma seleção inicial. Confira o estado do projeto quando for utilizá-lo, especialmente dependências e instruções de instalação. Simplefolio: para uma apresentação enxuta O Simplefolio é um template minimalista para desenvolvedores. Vale avaliá-lo quando você quer uma base visual discreta e prefere concentrar o trabalho na apresentação dos projetos. Uma estrutura enxuta também facilita perceber o que falta. Se o cartão de um projeto tem apenas título e imagem, acrescente uma descrição que explique o problema e sua contribuição. Escolha esse caminho quando você consegue revisar a base e quer evitar uma interface que concorra com o conteúdo. Examine o processo de instalação antes de assumir que ele se encaixa no ambiente atual do seu computador. Dopefolio: para organizar projetos com clareza O Dopefolio é um template de portfólio para desenvolvedores que merece avaliação quando você quer uma apresentação centrada nos trabalhos realizados. Ao personalizá-lo, dê atenção aos textos dos projetos. Substituir a captura de tela e manter uma descrição genérica deixa pouca informação para quem avalia. Escolha quando a organização visual combina com o material que você já tem. Se você só consegue preencher uma seção com conteúdo repetido, remova essa seção em vez de publicar uma página extensa sem informação adicional. developerFolio: para reunir uma trajetória mais ampla O developerFolio oferece seções para apresentar habilidades, experiência, formação e projetos. Pode servir para quem já tem material suficiente para preencher uma apresentação mais extensa. O repositório informa que o projeto não está sendo mantido ativamente. Avalie a base com atenção antes de adotá-la, principalmente se sua prioridade for publicar com pouca manutenção. Escolha quando você aceita revisar dependências e simplificar a estrutura. Não mantenha todas as seções apenas porque elas existem no template. HTML5 UP: para quem prefere uma base web tradicional O HTML5 UP disponibiliza templates de sites que podem ser adaptados para um portfólio. É uma opção para quem quer trabalhar com HTML e CSS sem transformar a apresentação em um projeto maior. Escolha um layout que dê espaço às descrições e às imagens do seu trabalho. Alguns formatos visuais podem exigir ajustes para acomodar estudos de caso. Confira também as condições de atribuição da licença. Gratuito não significa que você pode remover qualquer crédito ou reutilizar todos os elementos sem verificar as permissões. Como avaliar um template antes de baixar? Avalie licença, manutenção e organização do código antes de investir na personalização. A aparência da demonstração representa apenas uma parte do trabalho necessário para publicar o seu portfólio. Comece pelo arquivo de instruções. Ele deve ajudar você a entender como instalar, executar, editar e gerar a versão de publicação. Se essas etapas estão incompletas, considere esse esforço na escolha. Depois, examine onde ficam os dados. Nome, apresentação, projetos e informações de contato deveriam ser fáceis de encontrar. Uma configuração centralizada pode facilitar a manutenção, mas confira se ela é compreensível para você. Faça uma avaliação prática: Leia as condições de uso e os créditos exigidos. Confira as instruções e as dependências do projeto. Execute o template sem modificar o conteúdo. Verifique erros no terminal e no navegador. Troque um projeto de exemplo por um projeto seu. Teste a versão de publicação. Essa sequência ajuda a descobrir problemas antes de você passar horas ajustando cores e tipografia. Observe também o que o template carrega automaticamente. Integrações, widgets e bibliotecas de animação podem acrescentar trabalho sem melhorar a apresentação. Se uma função depende de uma configuração que você não entende, remova-a ou estude seu funcionamento antes de publicar. Um portfólio precisa ser uma base que você consegue explicar. Não coloque credenciais privadas no código enviado ao navegador. Para apresentar projetos, muitas vezes basta manter os dados localmente, sem consultar serviços externos durante cada visita. O que colocar no portfólio para demonstrar competência? Apresente projetos com contexto, contribuição e decisões verificáveis. Quem avalia precisa entender o que você fez e como a interface responde a situações reais. Escolha dois ou três trabalhos que revelem habilidades diferentes. Um formulário bem resolvido, uma interface com filtros e um projeto com integração podem produzir uma apresentação mais informativa do que várias páginas semelhantes. Para cada projeto, responda: Qual problema a interface resolve? Quem deveria utilizá-la? O que você implementou? Qual decisão técnica precisou tomar? Como verificou o funcionamento? O que ainda precisa melhorar? Explique uma decisão concreta Em vez de escrever “usei React para criar uma experiência moderna”, descreva uma escolha observável. Por exemplo: “Separei os filtros da lista de resultados para manter as opções selecionadas quando o usuário muda a ordenação.” Essa frase mostra uma relação entre implementação e comportamento. Você pode complementá-la com uma imagem ou uma demonstração do fluxo. Não precisa justificar cada linha de código. Escolha as decisões que ajudam outra pessoa a entender seu trabalho. Apresente estados além da tela principal Uma interface também precisa lidar com ausência de dados, carregamento e erros. Mostre esses estados quando fizerem parte do projeto. Em um catálogo, apresente o resultado de uma busca sem correspondências. Em um formulário, explique como as mensagens de erro ajudam a corrigir os campos. Em uma integração, mostre o que acontece quando a solicitação falha. Esses detalhes tornam o estudo de caso mais útil do que uma captura isolada da página inicial. Identifique sua participação Se o projeto foi feito em grupo, descreva sua responsabilidade. Se começou com um template, informe o que você adaptou e implementou. Também diferencie um projeto de estudo de um trabalho entregue a um cliente. Você pode demonstrar competência com ambos, desde que a apresentação corresponda ao que aconteceu. Não invente métricas. Quando não houver dados de uso, explique os testes realizados e as limitações conhecidas. Como personalizar o template sem perder tempo? Personalize primeiro o conteúdo e a hierarquia; depois ajuste a identidade visual. Essa ordem evita gastar tempo em efeitos que talvez precisem ser removidos quando os projetos entrarem na página. Comece pela frase de apresentação. Ela deve informar sua especialidade de forma clara. “Desenvolvedor frontend focado em interfaces acessíveis com React” comunica mais do que uma sequência de adjetivos. Em seguida, escolha qual projeto aparece primeiro. Use o trabalho que oferece a melhor combinação entre execução e explicação, mesmo que ele não seja o mais recente. Defina um pequeno conjunto de decisões visuais Escolha uma tipografia legível, uma cor de destaque e uma escala de espaçamento. Aplique essas decisões ao site inteiro. Evite mudar o estilo de cada seção. Quando os cartões, botões e títulos seguem padrões consistentes, o visitante consegue entender a página com menos esforço. Você também pode criar identidade com elementos discretos: uma capa de projeto bem composta
velog
Greenville, South Carolina rewards slow travelers. You can walk to a waterfall, follow a river trail, and eat a great dinner without starting a car. This guide covers the best things to do in Greenville SC if you only have a weekend. It also shares simple tips for saving money and getting around. Why Greenville Works for a Short Trip Downtown Greenville is compact. Falls Park on the Reedy sits a short walk from Main Street, and a free trolley loops through downtown. Greenville-Spartanburg International Airport (GSP) is about 25 minutes away. Charlotte is roughly two hours by road, Atlanta about two and a half, and Columbia under two. That makes Greenville an easy weekend escape from several Southeast cities. Getting to Greenville Without Overplanning You can drive, fly into GSP, or take an intercity bus. A bus works well here because you will not need a car for most downtown stops. Travelers who plan longer trips, such as the Los Angeles to Zacatecas bus route, follow the same basics as a Greenville weekend. Compare dates, check your stops, and confirm where you arrive. Keep a few honest tips in mind. Check that your route actually serves Greenville before you book. Schedules and prices change by date, so compare a few days. Confirm your arrival stop too, since it may sit outside downtown. Things to Do in Greenville, SC: Day One Start at Falls Park on the Reedy. Cross the Liberty Bridge for the best view of the waterfall. Go early if you want a quieter walk. Next, stroll Main Street without a fixed plan. Look for the Mice on Main, small bronze mice hidden along the street. They cost nothing, and kids love hunting for them. Eat lunch at Gather GVL, an outdoor food hall with 13 vendors. Then head to the West End. If the Greenville Drive are playing, catch a game at Fluor Field. Check the schedule first, because the season runs only through late summer. Finish with dinner at The Lazy Goat beside the Reedy River. Things to Do in Greenville SC: Day Two Spend the morning on the Swamp Rabbit Trail. The paved trail runs more than 32 miles to Travelers Rest. You do not need to ride all of it. Walk for an hour or rent a bike downtown, then turn around. If you visit on a Saturday, browse the TD Saturday Market first. It has more than 60 vendors. After lunch, pick one stop. The Greenville County Museum of Art displays American works by Andrew Wyeth and Jasper Johns, and admission is currently free. Families can visit the Greenville Zoo, which covers 14 acres inside Cleveland Park. Hikers should try Paris Mountain State Park. Got an extra day? Rent a car and head to Table Rock State Park or Caesars Head State Park. Best Things to Do in Greenville SC on a Budget Greenville costs less than many weekend cities if you lean on free stops. Falls Park and the Liberty Bridge Main Street and the Mice on Main The Swamp Rabbit Trail on foot Cleveland Park The free downtown trolley Check current hours and admission before you go, since details change. When to Visit Greenville Spring and fall suit trails and long walks. Summer brings events but also heat, so plan outdoor time for the morning. Winter feels quieter and works well for museums and restaurants. Food fans should look at Euphoria in September and Fall for Greenville in October. More Things to Do in Greenville SC This plan only covers the highlights. The BoletoXpress guide to things to do in Greenville SC lists more than 20 ideas. It includes rainy-day picks, nightlife, and options for couples and groups. Quick Tips Checklist Pack comfortable walking shoes. Book lodging downtown so you can skip the car. Check the Peace Center and Fluor Field calendars early. Bring a refillable water bottle for the trail. Plan outdoor stops for the morning in summer. Confirm bus or flight details a day before you travel. Leave open time to wander. FAQ How many days do you need in Greenville, SC? Two days cover the highlights. You can see Falls Park, Main Street, the Swamp Rabbit Trail, and a museum without rushing. Add a third day if you want to hike Paris Mountain or visit Table Rock State Park. One day also works if you stay downtown. What are the best free things to do in Greenville SC? Falls Park, the Liberty Bridge, Main Street, and the Mice on Main cost nothing. The Swamp Rabbit Trail is free to walk, and Cleveland Park is free to explore. The Greenville County Museum of Art currently offers free admission. Always check current details before you go. Is Greenville walkable without a car? Yes, downtown is very walkable. Falls Park, Main Street, the Peace Center, and the West End sit close together. A free trolley helps when your feet need a break. You will want a car only for farther stops like Paris Mountain, Table Rock, and Caesars Head. When is the best time to visit Greenville SC? Spring and fall offer the most comfortable weather for trails and walking. Fall also brings food festivals like Fall for Greenville in October. Summer works if you plan outdoor activities for early morning. Winter is quieter and suits museums, restaurants, and shows at the Peace Center. Can you take a bus to Greenville, SC? Intercity buses serve many Southeast cities, but service depends on your departure city and date. Check that your route actually reaches Greenville before you book. Compare schedules, confirm your arrival stop, and allow extra time for delays. Final Thoughts Greenville does not need a packed schedule. Pick a few stops, leave room to wander, and let the river, the trail, and the food do the work. BoletoXpress has more Greenville ideas whenever you want to extend the trip.
velog
변수에 값을 저장할 수 있게 되면 다음 단계는 그 값을 계산하고, 비교하고, 조건에 따라 다른 코드를 실행하고, 필요한 만큼 반복하는 것 이다. 이 글에서는 Java의 연산자와 String , 조건문, 반복문을 하나의 흐름으로 정리한다. 1. 연산자는 값을 가공하는 도구다 산술 연산자 int a = 10; int b = 3; System.out.println(a + b); // 13 System.out.println(a - b); // 7 System.out.println(a * b); // 30 System.out.println(a / b); // 3 System.out.println(a % b); // 1 정수끼리 나누면 결과도 정수이므로 소수 부분이 버려진다. System.out.println(5 / 2); // 2 System.out.println(5 / 2.0); // 2.5 % 는 나머지를 구한다. 짝수 여부나 주기적인 동작을 만들 때 유용하다. int index = 7; boolean isEven = index % 2 == 0; 증가·감소 연산자 int count = 0; count++; count--; 전위와 후위는 표현식 안에서 사용하는 시점 이 다르다. int value = 10; System.out.println(++value); // 11 value = 10; System.out.println(value++); // 10 System.out.println(value); // 11 단순히 값을 1 증가시키는 목적이라면 count++ 정도로만 사용하면 헷갈릴 일이 줄어든다. 2. 대입 연산자로 코드를 줄이기 int stock = 10; stock = stock + 3; 같은 코드는 복합 대입 연산자로 줄일 수 있다. stock += 3; stock -= 2; stock *= 2; stock /= 2; stock %= 3; 3. 비교와 논리 연산자로 조건 만들기 비교 연산의 결과는 boolean 이다. int age = 25; System.out.println(age > 19); // true System.out.println(age <= 30); // true System.out.println(age == 25); // true System.out.println(age != 20); // true 여러 조건을 합칠 때는 논리 연산자를 사용한다. boolean loggedIn = true; boolean hasPermission = false; boolean canAccess = loggedIn && hasPermission; boolean canPreview = loggedIn || hasPermission; boolean guest = !loggedIn; && : 양쪽이 모두 참일 때 true || : 하나라도 참이면 true ! : 참과 거짓을 뒤집음 && 와 || 는 단락 평가(short-circuit evaluation) 를 한다. 결과가 이미 결정되면 오른쪽 식을 실행하지 않는다. String token = null; if (token != null && token.length() > 10) { System.out.println("유효한 형식"); } 첫 번째 조건이 false 면 token.length() 는 실행되지 않아 NullPointerException 을 피할 수 있다. 4. 삼항 연산자는 짧은 값 선택에 적합하다 int score = 82; String result = score >= 60 ? "PASS" : "FAIL"; 간단한 값 선택에는 읽기 좋지만, 조건이 여러 단계로 중첩되면 if 문이 더 명확하다. 5. String 은 자주 쓰는 메소드부터 익히자 String path = " /api/orders "; System.out.println(path.length()); System.out.println(path.trim()); System.out.println(path.contains("orders")); System.out.println(path.startsWith("/api")); System.out.println(path.endsWith("orders")); System.out.println(path.indexOf("api")); System.out.println(path.replace("orders", "users")); 문자열은 불변 객체이므로 replace() , trim() 같은 메소드는 원본 문자열 자체를 수정하지 않고 새 문자열을 반환 한다. String original = "hello"; String upper = original.toUpperCase(); System.out.println(original); // hello System.out.println(upper); // HELLO 6. 문자열 비교는 equals() Java 입문에서 가장 중요한 실수 중 하나다. String a = new String("Java"); String b = new String("Java"); System.out.println(a == b); // false System.out.println(a.equals(b)); // true == 는 참조가 같은지 비교하고, equals() 는 문자열의 내용을 비교한다. 리터럴에서는 문자열 풀 때문에 우연히 == 가 true 가 나올 수 있다. String a = "Java"; String b = "Java"; System.out.println(a == b); // true일 수 있음 그래도 문자열 내용 비교는 항상 equals() 를 사용하는 습관을 들이는 것이 안전하다. null 가능성이 있는 값을 비교할 때는 상수를 앞에 두는 방법도 있다. if ("ACTIVE".equals(status)) { // ... } 7. 이스케이프 시퀀스 문자열 안에서 줄바꿈, 탭, 따옴표 같은 특수 문자를 표현할 때 사용한다. System.out.println("first\nsecond"); System.out.println("name\tvalue"); System.out.println("C:\\logs\\app.log"); System.out.println("\"Java\""); 8. if , else if , else 조건에 따라 실행할 코드를 나눌 때 사용한다. int statusCode = 404; if (statusCode >= 500) { System.out.println("서버 오류"); } else if (statusCode >= 400) { System.out.println("클라이언트 오류"); } else { System.out.println("정상 또는 리다이렉션"); } 여러 문장을 실행한다면 중괄호를 항상 사용하는 편이 실수를 줄인다. 9. switch : 값에 따라 분기하기 전통적인 형태는 다음과 같다. String role = "ADMIN"; switch (role) { case "ADMIN": System.out.println("관리자 권한"); break; case "USER": System.out.println("일반 사용자 권한"); break; default: System.out.println("알 수 없는 권한"); } break 를 생략하면 다음 case 까지 이어서 실행되는 fall-through 가 발생할 수 있다. 현대 Java에서는 화살표 형태의 switch 표현식도 사용할 수 있다. String label = switch (role) { case "ADMIN" -> "관리자"; case "USER" -> "사용자"; default -> "알 수 없음"; }; 단순한 값 매핑에서는 이 형태가 더 읽기 쉽다. 10. for : 반복 횟수를 알 때 for (int i = 0; i < 5; i++) { System.out.println("request-" + i); } 실행 흐름은 다음 순서다. 초기화 → 조건 확인 → 본문 실행 → 증감 → 조건 확인 → ... 중첩 반복문도 만들 수 있다. for (int page = 1; page <= 3; page++) { for (int item = 1; item <= 2; item++) { System.out.println("page=" + page + ", item=" + item); } } 바깥쪽 3회 × 안쪽 2회이므로 본문은 총 6회 실행된다. 11. while : 조건이 유지되는 동안 반복 횟수보다 조건 이 중요할 때 사용한다. int retry = 0; while (retry < 3) { System.out.println("API 재시도: " + retry); retry++; } 조건이 계속 true 라면 무한 반복이 발생하므로 반복문 안에서 조건을 바꿀 수 있는지 확인해야 한다. 12. do-while : 최소 한 번은 실행 int retry = 0; do { System.out.println("요청 실행"); retry++; } while (retry < 3); while 과 달리 조건을 나중에 검사하므로 본문이 최소 한 번 실행된다. 13. break 와 continue break 는 반복문을 즉시 끝낸다. for (int i = 0; i < 10; i++) { if (i == 3) { break; } System.out.println(i); } continue 는 현재 회차의 남은 코드를 건너뛰고 다음 반복으로 이동한다. for (int i = 0; i < 5; i++) { if (i == 2) { continue; } System.out.println(i); } 핵심 정리 산술 연산자에는 + , - , * , / , % 가 있다. 정수끼리 나누면 결과의 소수 부분은 버려진다. 비교 연산은 boolean 을 만들고, && , || , ! 로 조건을 조합할 수 있다. 문자열의 내용 비교는 == 가 아니라 equals() 를 사용한다. if 는 범위 조건, switch 는 명확한 값 분기에 잘 맞는다. for 는 반복 횟수가 명확할 때, while 은 조건 중심 반복에 적합하다. do-while 은 본문을 최소 한 번 실행한다. break 는 반복 종료, continue 는 현재 회차만 건너뛴다.
velog
Java를 제대로 이해하려면 문법보다 객체지향 프로그래밍(OOP) 을 이해하는 것이 중요하다. 객체지향의 핵심은 데이터를 따로 두고 함수를 따로 두는 것이 아니라, 서로 관련 있는 상태와 행동을 하나의 객체로 묶어 프로그램을 구성하는 것 이다. 1. 클래스와 객체 클래스는 객체를 만들기 위한 설계도처럼 생각할 수 있다. class Product { String name; int price; } 객체는 new 로 생성한다. Product product = new Product(); product.name = "Keyboard"; product.price = 89000; 같은 클래스로 여러 객체를 만들 수 있고 각 객체는 서로 다른 값을 가질 수 있다. Product keyboard = new Product(); Product mouse = new Product(); 2. 인스턴스 변수와 인스턴스 메소드 객체마다 서로 다른 상태를 가지는 필드는 인스턴스 변수다. class User { String name; int point; void addPoint(int amount) { point += amount; } } User user = new User(); user.name = "developer"; user.point = 100; user.addPoint(50); user.point 와 user.addPoint() 처럼 . 을 이용해 객체의 멤버에 접근한다. 3. static : 객체가 아니라 클래스에 속하는 값 모든 객체가 공유해야 하는 값이나 기능은 static 으로 선언할 수 있다. class User { static int userCount = 0; } System.out.println(User.userCount); 클래스 메소드도 객체 없이 호출할 수 있다. class IdGenerator { static String create(String prefix, int id) { return prefix + "-" + id; } } String orderId = IdGenerator.create("ORDER", 1001); 인스턴스에 의존하지 않는 기능이라면 static 이 자연스러울 수 있지만, 모든 것을 static 으로 만들면 객체지향 설계의 장점을 잃기 쉽다. 4. this : 현재 객체를 가리키기 필드 이름과 매개변수 이름이 같을 때 this 로 현재 객체의 필드를 구분할 수 있다. class User { String name; void setName(String name) { this.name = name; } } this.name 은 현재 객체의 필드, 오른쪽 name 은 메소드가 받은 매개변수다. 5. 생성자로 객체의 초기 상태 보장하기 생성자는 객체가 만들어질 때 호출된다. class Product { String name; int price; Product(String name, int price) { this.name = name; this.price = price; } } Product product = new Product("Keyboard", 89000); 필수값을 생성자에서 받게 하면 불완전한 객체가 만들어질 가능성을 줄일 수 있다. 6. 캡슐화와 Getter/Setter 필드를 외부에 직접 공개하기보다 private 으로 감추고 필요한 접근 방법만 제공할 수 있다. class Account { private int balance; public int getBalance() { return balance; } public void deposit(int amount) { if (amount <= 0) { return; } balance += amount; } } 모든 필드에 기계적으로 Getter/Setter를 만드는 것보다 객체가 스스로 유효한 상태를 유지하도록 의미 있는 메소드를 제공하는 것 이 더 좋은 객체지향 설계인 경우가 많다. 7. 접근 제어자 접근 제어자 접근 범위 private 같은 클래스 내부 package-private 같은 패키지 내부 protected 같은 패키지 + 다른 패키지의 하위 클래스 public 어디서든 접근 가능 아무 접근 제어자도 쓰지 않은 경우를 흔히 default 라고 부르지만, Java 문법의 키워드 default 와 혼동하지 않도록 package-private 라고 부르는 편이 정확하다. 8. 패키지와 import 패키지는 관련 클래스를 묶어 이름 충돌을 줄이고 구조를 만든다. package com.example.order; 다른 패키지의 클래스를 사용할 때는 import 를 사용할 수 있다. import java.util.ArrayList; 프로젝트가 커질수록 기능이나 도메인 기준으로 패키지를 나누게 된다. com.example ├── user ├── order └── payment 9. 상속: 기존 기능을 확장하기 class Notification { void send() { System.out.println("알림 전송"); } } class EmailNotification extends Notification { String email; } EmailNotification 은 Notification 의 기능을 물려받는다. 하지만 코드 재사용만을 이유로 무조건 상속을 선택하면 결합도가 높아질 수 있다. 실제 설계에서는 is-a 관계가 자연스러운지 먼저 생각하는 것이 좋다. 10. 오버라이딩 자식 클래스는 부모 메소드를 다시 정의할 수 있다. class Notification { public void send() { System.out.println("기본 알림"); } } class EmailNotification extends Notification { @Override public void send() { System.out.println("이메일 알림"); } } @Override 는 필수는 아니지만 실수를 컴파일 단계에서 찾는 데 도움이 되므로 붙이는 것이 좋다. 11. 다형성 부모 타입 변수로 자식 객체를 가리킬 수 있다. Notification notification = new EmailNotification(); notification.send(); 실제 객체가 EmailNotification 이므로 오버라이딩된 메소드가 실행된다. 이 성질을 사용하면 여러 구현을 같은 방식으로 다룰 수 있다. Notification[] notifications = { new EmailNotification(), new SmsNotification() }; for (Notification notification : notifications) { notification.send(); } 호출하는 쪽은 구체적인 구현 세부사항보다 Notification 이라는 공통 타입에 의존할 수 있다. 12. super : 부모 클래스에 접근하기 부모 생성자를 호출할 수 있다. class User { final String id; User(String id) { this.id = id; } } class AdminUser extends User { String role; AdminUser(String id, String role) { super(id); this.role = role; } } super(...) 는 부모 생성자를 호출한다. super.method() 처럼 부모의 메소드에 접근할 수도 있다. 13. 참조와 객체 공유 참조 자료형 변수를 대입하면 객체 자체가 복사되는 것이 아니라 같은 객체를 가리키게 될 수 있다. User a = new User(); a.name = "A"; User b = a; b.name = "B"; System.out.println(a.name); // B a 와 b 가 같은 객체를 참조하기 때문이다. 이 개념은 이후 컬렉션, 메소드 전달, 불변 객체를 이해할 때 매우 중요하다. 14. final 의 세 가지 사용 변수 재대입할 수 없다. final int maxRetry = 3; 참조 변수에 final 을 붙이면 참조를 다른 객체로 바꿀 수 없다는 뜻 이지 객체 내부까지 자동으로 불변이 되는 것은 아니다. 메소드 자식 클래스에서 오버라이딩할 수 없다. public final void validate() { // ... } 클래스 상속할 수 없다. final class TokenParser { } 15. enum : 정해진 값의 집합 문자열로 상태를 관리하면 오타를 컴파일러가 잡지 못한다. String status = "PAID"; 정해진 값만 허용하려면 enum 이 안전하다. enum OrderStatus { CREATED, PAID, SHIPPED, CANCELED } OrderStatus status = OrderStatus.PAID; 16. 추상 클래스 공통 상태와 구현을 가지면서 일부 동작은 자식에게 맡기고 싶을 때 사용할 수 있다. abstract class PaymentProcessor { abstract boolean pay(int amount); public void log() { System.out.println("결제 처리"); } } class CardPaymentProcessor extends PaymentProcessor { @Override public boolean pay(int amount) { return amount > 0; } } 추상 클래스 자체는 직접 인스턴스화할 수 없다. 17. 인터페이스 인터페이스는 구현체가 따라야 할 동작의 계약을 표현하기 좋다. interface Storage { void save(String data); } class FileStorage implements Storage { @Override public void save(String data) { System.out.println("파일 저장: " + data); } } 인터페이스의 추상 메소드는 기본적으로 public 이므로 구현 메소드 역시 접근 범위를 더 좁힐 수 없다. 하나의 클래스는 여러 인터페이스를 구현할 수 있다. class CloudStorage implements Storage, AutoCloseable { @Override public void save(String data) { } @Override public void close() { } } 추상 클래스와 인터페이스, 무엇을 선택할까? 공통 상태와 구현을 공유하는 밀접한 계층 구조 가 필요하면 추상 클래스가 자연스럽고, 서로 다른 클래스들이 공통된 행동 계약 을 가져야 한다면 인터페이스가 유연하다. 둘 중 하나만 고집하기보다 역할에 맞게 함께 사용하는 경우가 많다. 핵심 정리 클래스는 데이터와 동작을 묶고, 객체는 클래스로부터 만들어진 인스턴스다. static 멤버는 객체가 아니라 클래스에 속한다. this 는 현재 객체, super 는 부모 부분에 접근할 때 사용한다. 생성자는 객체의 초기 상태를 설정한다. private 과 의미 있는 메소드를 사용하면 객체의 상태를 안전하게 관리할 수 있다. 상속과 오버라이딩을 통해 기능을 확장할 수 있다. 다형성은 부모 타입으로 여러 자식 구현을 동일하게 다루게 해준다. 추상 클래스와 인터페이스는 공통 규칙과 구현 구조를 설계할 때 사용한다.
velog
1차원/2차원 배열과 포인터 int a[3] = {1,2,3}; int b[2][3] = {{1,2,3},{4,5,6}}; 구분 선언 가리키는 대상 원소 접근 1차원 배열의 원소 포인터 int *p = a; 정수 하나 p[1] 1차원 배열 전체의 포인터 int (*p)[3] = &a; 정수 3개짜리 배열 (*p)[1] 2차원 배열의 행 포인터 int (*p)[3] = b; 정수 3개짜리 행 p[1][2] 2차원 배열 전체의 포인터 int (*p)[2][3] = &b; 2행 3열 배열 전체 (*p)[1][2] 배열 이름은 대부분의 표현식에서 첫 번째 원소를 가리키는 포인터로 변환된다. -> sizeof 연산자와 주소값 연산자 & 를 사용할 때 빼고. 2차원 배열의 첫 번째 원소는 행 배열이므로, b 는 int (*)[3] 으로 변환된다. &a , `&b는 각각 배열의 전체 주소를 나타낸다. p + 1 은 포인터가 가리키는 자료형의 크기만큼 이동한다. 2차원 배열은 int ** 가 아니다. 2차원 배열 포인터를 통해 배열에 접근하기 위해서는 가리키는 원소의 크기(타입) 열의 크기 가 필요하다. 배열 포인터 vs 포인터 배열
Балл: 54.4Уверенность: 49%
Подробнееvelog
문법만 알고 프로그램을 만들면 곧 세 가지 현실적인 문제를 만나게 된다. 예상하지 못한 입력이나 오류가 발생한다. 여러 작업을 동시에 처리해야 한다. 콘솔이나 파일처럼 프로그램 외부와 데이터를 주고받아야 한다. Java에서는 각각 예외 처리 , 스레드 , 입출력 API 로 대응한다. 1. 예외는 프로그램 실행 중 발생하는 문제 상황이다 예를 들어 존재하지 않는 배열 인덱스에 접근하면 예외가 발생한다. int[] values = {10, 20, 30}; System.out.println(values[5]); 프로그램에서 예상 가능한 문제를 처리하려면 try-catch 를 사용한다. try { int[] values = {10, 20, 30}; System.out.println(values[5]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("잘못된 인덱스입니다."); } 가능하면 무조건 Exception 하나로 잡기보다 처리할 수 있는 구체적인 예외 를 잡는 편이 의도가 명확하다. 2. 여러 catch 로 예외 종류를 나누기 try { int page = Integer.parseInt(input); System.out.println(values[page]); } catch (NumberFormatException e) { System.out.println("숫자 형식이 아닙니다."); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("범위를 벗어났습니다."); } 예외 종류에 따라 다른 복구 전략을 적용할 수 있다. 3. throw : 의도적으로 예외 발생시키기 잘못된 상태를 그냥 통과시키지 않고 예외로 표현할 수 있다. public static void validateAmount(int amount) { if (amount < 0) { throw new IllegalArgumentException("금액은 0 이상이어야 합니다."); } } 이렇게 하면 호출하는 쪽에서 오류를 명확하게 인식할 수 있다. 4. finally : 성공해도 실패해도 실행 try { System.out.println("작업 시작"); } catch (Exception e) { System.out.println("문제 발생"); } finally { System.out.println("작업 종료"); } finally 는 예외 발생 여부와 관계없이 실행된다. 과거에는 파일이나 네트워크 자원을 닫는 데 많이 사용했지만, 닫을 수 있는 자원은 try-with-resources 가 더 안전한 경우가 많다. 5. try-with-resources AutoCloseable 을 구현한 자원은 블록이 끝날 때 자동으로 닫힌다. import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; try (BufferedWriter writer = new BufferedWriter(new FileWriter("app.log"))) { writer.write("application started"); } catch (IOException e) { System.out.println("파일 저장 실패"); } 정상 종료뿐 아니라 예외가 발생한 경우에도 close() 가 호출되므로 자원 누수를 줄일 수 있다. 6. 사용자 정의 예외 도메인에 맞는 오류 의미를 표현하고 싶다면 직접 예외 클래스를 만들 수 있다. class InsufficientStockException extends Exception { public InsufficientStockException(String message) { super(message); } } public static void validateStock(int stock, int quantity) throws InsufficientStockException { if (stock < quantity) { throw new InsufficientStockException("재고가 부족합니다."); } } 7. throws : 예외 처리를 호출한 곳으로 넘기기 public static String loadConfig() throws IOException { // 파일 읽기 return "config"; } 메소드가 직접 해결하기 어려운 예외를 상위 호출자에게 맡길 수 있다. throw 는 예외를 실제로 발생시키는 것 , throws 는 이 메소드가 예외를 바깥으로 전달할 수 있음을 선언하는 것 이다. 8. 스레드란? 스레드는 하나의 프로세스 안에서 실행되는 작업 흐름이다. 여러 스레드를 사용하면 여러 작업이 동시성(concurrency) 을 가지게 할 수 있다. 여러 CPU 코어에서 실제로 동시에 실행될 수도 있지만, 스레드를 만들었다고 항상 물리적으로 병렬 실행되는 것은 아니다. 스케줄러와 실행 환경에 따라 달라진다. Thread 상속 class LogThread extends Thread { @Override public void run() { for (int i = 1; i <= 3; i++) { System.out.println("log " + i); } } } Thread thread = new LogThread(); thread.start(); run() 을 직접 호출하는 것과 start() 는 다르다. 새 스레드에서 실행하려면 start() 를 호출해야 한다. 9. Runnable 구현 동작을 객체로 분리하려면 Runnable 을 사용할 수 있다. Runnable task = () -> { for (int i = 1; i <= 3; i++) { System.out.println("task " + i); } }; Thread thread = new Thread(task); thread.start(); Thread 를 직접 상속하지 않으므로 다른 클래스를 상속해야 하는 경우에도 사용할 수 있다. 실무에서는 낮은 수준의 Thread 를 직접 많이 만들기보다 Executor 계열 API나 가상 스레드 같은 더 높은 수준의 동시성 도구를 사용하는 경우가 많지만, Thread 와 Runnable 의 기본 원리를 이해하면 이후 개념을 익히기 쉽다. 10. join() : 다른 스레드가 끝날 때까지 기다리기 Thread worker = new Thread(() -> { System.out.println("백그라운드 작업"); }); worker.start(); worker.join(); System.out.println("작업 완료 후 실행"); join() 은 대상 스레드가 종료될 때까지 현재 스레드를 기다리게 한다. InterruptedException 처리가 필요할 수 있다. 11. 공유 데이터와 경쟁 상태 여러 스레드가 같은 값을 동시에 수정하면 예상하지 못한 결과가 나올 수 있다. class Counter { int value = 0; void increment() { value++; } } value++ 는 겉보기와 달리 읽기 → 증가 → 쓰기 과정이므로 여러 스레드가 동시에 실행하면 증가가 유실될 수 있다. 12. synchronized 로 임계 구역 보호하기 class Counter { private int value = 0; public synchronized void increment() { value++; } public int getValue() { return value; } } 한 번에 하나의 스레드만 increment() 의 임계 구역에 들어가게 해 경쟁 상태를 줄인다. 블록 단위로 특정 객체를 락으로 사용할 수도 있다. synchronized (lock) { // 공유 자원 접근 } 동기화는 안전성을 높이지만 락 경쟁이 많으면 성능에 영향을 줄 수 있다. 필요한 범위를 작게 잡는 것이 중요하다. 13. Scanner 로 콘솔 입력 받기 import java.util.Scanner; Scanner scanner = new Scanner(System.in); System.out.print("페이지 번호: "); int page = scanner.nextInt(); System.out.println("입력된 페이지: " + page); 대표 메소드는 다음과 같다. next() : 공백 전까지 한 단어 nextInt() : 정수 nextDouble() : 실수 nextLine() : 한 줄 전체 nextInt() 뒤에 바로 nextLine() 을 사용하면 남아 있던 줄바꿈 문자를 읽어 빈 문자열처럼 보일 수 있다. 이 동작은 콘솔 입력을 처음 다룰 때 자주 헷갈린다. 14. print , println , printf System.out.print("A"); System.out.println("B"); System.out.printf("status=%d, path=%s%n", 200, "/api/users"); printf 에서 자주 사용하는 형식 지정자는 다음과 같다. %d : 정수 %f : 실수 %s : 문자열 %n : 플랫폼에 맞는 줄바꿈 System.out.printf("%,d%n", 1234567); // 1,234,567 System.out.printf("%.2f%n", 3.14159); // 3.14 System.out.printf("%04d%n", 12); // 0012 15. 파일과 폴더 다루기 전통적인 File API로 존재 여부와 경로 정보 등을 다룰 수 있다. import java.io.File; File file = new File("app.log"); System.out.println(file.exists()); System.out.println(file.getName()); System.out.println(file.getAbsolutePath()); System.out.println(file.length()); File folder = new File("logs"); folder.mkdir(); 현대 Java에서는 java.nio.file.Path 와 Files API도 많이 사용한다. import java.nio.file.Files; import java.nio.file.Path; Path path = Path.of("logs", "app.log"); Files.createDirectories(path.getParent()); 16. 파일 쓰기와 읽기 쓰기 import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; try (BufferedWriter writer = new BufferedWriter(new FileWriter("app.log"))) { writer.write("server started"); writer.newLine(); writer.write("port=8080"); } catch (IOException e) { System.out.println("파일 쓰기 실패"); } 읽기 import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; try (BufferedReader reader = new BufferedReader(new FileReader("app.log"))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { System.out.println("파일 읽기 실패"); } readLine() 이 더 읽을 내용이 없으면 null 을 반환하므로 while 문으로 파일 끝까지 읽을 수 있다. 핵심 정리 try-catch 로 실행 중 발생 가능한 예외를 처리한다. throw 는 예외를 발생시키고, throws 는 예외를 호출자에게 전달할 수 있음을 선언한다. 닫아야 하는 자원은 try-with-resources 를 사용하면 안전하다. Thread.start() 는 새 스레드에서 run() 을 실행한다. join() 은 다른 스레드가 끝날 때까지 기다린다. 공유 데이터를 여러 스레드가 수정하면 경쟁 상태가 발생할 수 있다. synchronized 는 임계 구역의 동시 접근을 제어한다. Scanner , printf , 파일 API를 이용해 프로그램 외부와 데이터를 주고받을 수 있다.
velog
프로그램이 조금만 커져도 변수를 하나씩 만들고 같은 코드를 반복해서 작성하는 방식은 금방 한계가 온다. Java에서는 배열 로 같은 타입의 데이터를 묶고, 메소드 로 반복되는 동작을 하나의 기능 단위로 나눌 수 있다. 1. 배열이 필요한 이유 상품 가격이 다섯 개 있다고 해보자. int price1 = 12000; int price2 = 18000; int price3 = 9500; int price4 = 22000; int price5 = 15000; 값이 늘어날수록 관리가 어려워진다. 같은 자료형의 값을 하나로 묶으면 훨씬 다루기 쉽다. int[] prices = {12000, 18000, 9500, 22000, 15000}; 2. 배열 만들기 크기를 먼저 정할 수 있다. int[] statusCodes = new int[3]; 각 요소는 인덱스로 접근한다. 인덱스는 0부터 시작한다. statusCodes[0] = 200; statusCodes[1] = 404; statusCodes[2] = 500; 배열의 길이는 length 로 확인한다. System.out.println(statusCodes.length); // 3 범위를 벗어난 인덱스에 접근하면 ArrayIndexOutOfBoundsException 이 발생한다. System.out.println(statusCodes[3]); // 예외 3. 배열 초기화 방법 String[] environments = new String[] { "dev", "staging", "production" }; 선언과 동시에 값을 넣는다면 new String[] 을 생략할 수 있다. String[] environments = {"dev", "staging", "production"}; 일반적으로 String environments[] 보다 String[] environments 형태가 자료형을 더 명확하게 보여주므로 많이 사용한다. 4. 배열 순회 인덱스가 필요할 때 int[] latencies = {120, 85, 210}; for (int i = 0; i < latencies.length; i++) { System.out.println(i + ": " + latencies[i]); } 값만 필요할 때 향상된 for 문을 사용할 수 있다. for (int latency : latencies) { System.out.println(latency); } 인덱스를 직접 수정하거나 위치 정보가 필요한 작업이 아니라면 향상된 for 문이 간결하다. 5. 2차원 배열 행과 열처럼 데이터를 구성할 때 사용할 수 있다. int[][] traffic = { {120, 130, 140}, {200, 210, 220} }; System.out.println(traffic[0][1]); // 130 중첩 반복문으로 순회할 수 있다. for (int row = 0; row < traffic.length; row++) { for (int col = 0; col < traffic[row].length; col++) { System.out.println(traffic[row][col]); } } 각 행마다 길이가 다를 수도 있으므로 안쪽 반복문의 조건은 traffic[row].length 처럼 작성하는 것이 안전하다. 6. 문자와 숫자의 관계 Java의 char 는 숫자 값으로도 표현할 수 있다. char upperA = 'A'; int code = upperA; System.out.println(code); // 65 ASCII 기준으로 숫자 '0' 은 48, 대문자 'A' 는 65, 소문자 'a' 는 97부터 시작한다. 하지만 Java 문자열 전체를 ASCII로만 이해하면 안 된다. Java는 유니코드를 다루며 char 는 UTF-16 코드 단위를 표현한다. 7. 메소드는 기능을 이름 붙인 코드 묶음이다 같은 코드를 여러 번 사용해야 한다면 메소드로 분리할 수 있다. public static void printSeparator() { System.out.println("----------------"); } public static void main(String[] args) { printSeparator(); System.out.println("사용자 목록"); printSeparator(); } 메소드를 사용하면 중복이 줄고 코드의 의도가 이름으로 드러난다. 8. 매개변수와 인자 메소드가 외부 값을 받도록 만들 수 있다. public static void printUser(String name) { System.out.println("user=" + name); } printUser("kim"); 엄밀히 구분하면 메소드 선언부의 name 은 매개변수(parameter) , 호출할 때 전달한 "kim" 은 인자(argument) 다. 여러 값을 받을 수도 있다. public static void printOrder(String orderId, int amount) { System.out.println(orderId + ": " + amount); } 9. 반환값 계산 결과를 호출한 곳으로 돌려주려면 반환형과 return 을 사용한다. public static int calculateTotal(int price, int quantity) { return price * quantity; } int total = calculateTotal(15000, 3); System.out.println(total); // 45000 반환값이 없는 메소드는 void 를 사용한다. public static void log(String message) { System.out.println(message); } 10. 메소드 오버로딩 같은 이름이지만 매개변수의 개수나 타입이 다른 메소드를 여러 개 정의할 수 있다. public static int add(int a, int b) { return a + b; } public static int add(int a, int b, int c) { return a + b + c; } public static double add(double a, double b) { return a + b; } 반환형만 다르게 만드는 것은 오버로딩이 아니다. // 컴파일 불가 int parse(String value) { ... } double parse(String value) { ... } 호출 시 어떤 메소드를 사용할지 매개변수 목록으로 구분할 수 있어야 한다. 11. 메소드를 쓰면 무엇이 좋아질까? 예를 들어 주문 금액 검증이 여러 위치에서 반복된다고 해보자. if (amount < 0) { System.out.println("잘못된 금액"); } 이를 메소드로 분리하면 규칙을 한곳에서 관리할 수 있다. public static boolean isValidAmount(int amount) { return amount >= 0; } if (!isValidAmount(amount)) { System.out.println("잘못된 금액"); } 이렇게 하면 코드가 무엇을 검사하는지 더 잘 보이고, 규칙이 바뀌어도 메소드 하나만 수정하면 된다. 12. 변수의 범위: Scope 메소드나 블록 안에서 선언한 지역 변수는 해당 범위를 벗어나면 사용할 수 없다. public static void main(String[] args) { int count = 10; if (count > 0) { String message = "데이터 있음"; System.out.println(message); } // System.out.println(message); // 사용 불가 } 지역 변수의 범위를 필요 이상으로 넓게 잡지 않으면 코드의 상태를 추적하기 쉬워진다. 13. main 메소드의 역할 전통적인 Java 애플리케이션의 시작점은 다음 메소드다. public static void main(String[] args) { // 프로그램 시작 } public : JVM이 외부에서 호출할 수 있음 static : 객체를 만들지 않고 실행 가능 void : 반환값 없음 String[] args : 실행 시 전달받는 문자열 인자 명령행 인자를 사용할 수도 있다. public static void main(String[] args) { if (args.length > 0) { System.out.println("mode=" + args[0]); } } 핵심 정리 배열은 같은 자료형의 여러 값을 하나의 변수로 관리한다. 배열 인덱스는 0부터 시작하고 길이는 array.length 로 확인한다. 인덱스가 필요하면 일반 for , 값만 필요하면 향상된 for 가 편리하다. 2차원 배열은 array[row][col] 형태로 접근한다. 메소드는 특정 기능을 수행하는 코드 묶음이다. 매개변수로 값을 받고 return 으로 결과를 반환할 수 있다. 오버로딩은 같은 이름과 서로 다른 매개변수 목록을 가진 메소드를 정의하는 것이다. 지역 변수는 선언된 블록 안에서만 사용할 수 있다.
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%
Балл: 54.4Уверенность: 49%