implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
public interface ApiService {
@GET("users")
Call<List<User>> getUsers();
}
ApiService apiService = retrofit.create(ApiService.class);
apiService.getUsers().enqueue(new Callback>() {
@Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
if (response.isSuccessful()) {
List<User> users = response.body();
// Обработка данных
} else {
// Обработка ошибки
}
}
@Override
public void onFailure(Call<List<User>> call, Throwable t) {
// Обработка ошибки сети
}
});
public class User {
private int id;
private String name;
public int getId() {
return id;
}
public String getName() {
return name;
}
}
public interface ApiService {
@GET("users/{id}")
Call<User> getUser(@Path("id") int userId);
}
apiService.getUser(1).enqueue(new Callback() {
@Override
public void onResponse(Call<User> call, Response response) {
if (response.isSuccessful()) {
User user = response.body();
// Обработка данных пользователя
}
}
@Override
public void onFailure(Call<User> call, Throwable t) {
// Обработка ошибки сети
}
});
public interface ApiService {
@GET("users")
Call<List<User>> getUsers(@Header("Authorization") String token);
}
public interface ApiService {
@POST("users")
Call<User> createUser(@Body User user);
@GET("users")
Call<List<User>> getUsers(@Query("page") int page);
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Java является строго типизированным языком программирования, а это означает, то что каждое выражение и каждая переменная имеет строго определенный тип уже на момент компиляции. Однако определен механизм приведения типов (casting) - способ преобразования значения переменной одного типа в значение другого типа.
В Java существуют несколько разновидностей приведения:
✔️ Тождественное (identity). Преобразование выражения любого типа к точно такому же типу всегда допустимо и происходит автоматически.
✔️ Расширение (повышение, upcasting) примитивного типа (widening primitive). Означает, что осуществляется переход от менее емкого типа к более ёмкому. Например, от типа
byte (длина 1 байт) к типу int (длина 4 байта). Такие преобразование безопасны в том смысле, что новый тип всегда гарантировано вмещает в себя все данные, которые хранились в старом типе и таким образом не происходит потери данных. Этот тип приведения всегда допустим и происходит автоматически.✔️ Сужение (понижение, downcasting) примитивного типа (narrowing primitive). Означает, что переход осуществляется от более емкого типа к менее емкому. При таком преобразовании есть риск потерять данные. Например, если число типа
int было больше 127, то при приведении его к byte значения битов старше восьмого будут потеряны. В Java такое преобразование должно совершаться явным образом, при этом все старшие биты, не умещающиеся в новом типе, просто отбрасываются - никакого округления или других действий для получения более корректного результата не производится.✔️ Расширение объектного типа (widening reference). Означает неявное восходящее приведение типов или переход от более конкретного типа к менее конкретному, т.е. переход от потомка к предку. Разрешено всегда и происходит автоматически.
✔️ Сужение объектного типа (narrowing reference). Означает нисходящее приведение, то есть приведение от предка к потомку (подтипу). Возможно только если исходная переменная является подтипом приводимого типа. При несоответствии типов в момент выполнения выбрасывается исключение
ClassCastException. Требует явного указания типа.✔️ Преобразование к строке (to String). Любой тип может быть приведен к строке, т.е. к экземпляру класса
String.✔️ Запрещенные преобразования (forbidden). Не все приведения между произвольными типами допустимы. Например, к запрещенным преобразованиям относятся приведения от любого ссылочного типа к примитивному и наоборот (кроме преобразования к строке). Кроме того, невозможно привести друг к другу классы, находящиеся на разных ветвях дерева наследования и т.п.
При приведении ссылочных типов с самим объектом ничего не происходит, - меняется лишь тип ссылки, через которую происходит обращение к объекту.
Для проверки возможности приведения нужно воспользоваться оператором
instanceof:
Parent parent = new Child();
if (parent instanceof Child) {
Child child = (Child) parent;
}
#java #casting #upcasting #downcasting
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤2
Использование "сырых" типов коллекций (вроде
List вместо List<String>) опасно! Generics (<>) обеспечивают безопасность типов на этапе компиляции.
// Опасно - можно добавить что угодно, ошибка будет при извлечении
List unsafeList = new ArrayList();
unsafeList.add("Привет");
unsafeList.add(123); // Компилятор не ругается!
// String s = (String) unsafeList.get(1); // ClassCastException во время выполнения!
// Безопасно - только строки!
List<String> safeList = new ArrayList<>();
safeList.add("Привет");
// safeList.add(123); // Ошибка компиляции! Нельзя добавить int в List<String>
String s = safeList.get(0); // Никакого приведения типов не нужно!
#java #generics #typesafety #bestpractice
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤1
Старый API даты/времени был неудобным и изменяемым (mutable). Новый пакет
java.time (LocalDate, LocalTime, LocalDateTime, ZonedDateTime, Duration, Period) решает эти проблемы!
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.ChronoUnit;
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(2024, Month.DECEMBER, 31);
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); // Неизменяемый! Возвращает новый объект
System.out.println("Сегодня: " + today);
System.out.println("День рождения: " + birthday);
System.out.println("Через неделю: " + nextWeek);
// Вывод:
// Сегодня: 2023-10-27 (пример)
// День рождения: 2024-12-31
// Через неделю: 2023-11-03 (пример)
Используйте современный, потокобезопасный и интуитивно понятный API! ✨
#java #datetime #java8 #javatime #api #bestpractice
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤1🔥1👏1
Ключевое слово
interface используется для создания полностью абстрактных классов. Основное предназначение интерфейса - определять каким образом мы можем использовать класс, который его реализует. Создатель интерфейса определяет имена методов, списки аргументов и типы возвращаемых значений, но не реализует их поведение. Все методы неявно объявляются как public.Начиная с Java 8 в интерфейсах разрешается размещать реализацию методов по умолчанию
default и статических static методов.Интерфейс также может содержать и поля. В этом случае они автоматически являются публичными
public, статическими static и неизменяемыми final.Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤2
Java поддерживает Unicode во всех частях кода, включая комментарии и имена переменных. Это открывает неочевидные возможности для экспериментов, но требует осторожности в production-коде.
// \u000d System.out.println("Этот код выполнится!");
После компиляции символ
\u000d превращается в перенос строки, и код становится:
//
System.out.println("Этот код выполнится!");
Применение:
▸ Демонстрация скрытых уязвимостей в презентациях
▸ Образовательные эксперименты с компиляцией
▸ Технические розыгрыши (только для небоевых проектов!)
int размер = 10; // переменная "размер"
System.out.println(размер); // 10
▸ Локализация кода для образовательных проектов
▸ Поддержка специфических терминов на национальных языках
System.out.println("\u2591\u2592\u2593"); // Вывод символов псевдографики: ░ ▒ ▓ (разные уровни заливки)
System.out.println("\u265A \u265B"); // Вывод юникод-символов: ♚ ♛ (шахматные фигуры короля и королевы)
▸ Консольные интерфейсы с псевдографикой
▸ Визуализация данных в текстовом режиме
▸ Генерация ASCII-арта
String regex = "\\p{So}"; // Шаблон для эмодзи и символов
String text = "Alert! ⚠️";
System.out.println(text.replaceAll(regex, "[символ]")); // Alert! [символ]
⚠️ Важные предупреждения:
▸ Код с Unicode-трюками не проходит код-ревью в серьезных проектах
▸ Может вызывать проблемы с линтерами и статическими анализаторами
▸ Затрудняет поиск в кодовой базе (например,
\u000d)
// Локализация через ResourceBundle
ResourceBundle bundle = ResourceBundle.getBundle("Messages_ru"); // Загрузка ресурсов для локали ru
String message = bundle.getString("welcome"); // Получение локализованной строки по ключу
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1
ThreadLocal— потокобезопасное хранилище данных ThreadLocal позволяет хранить данные, уникальные для каждого потока, без использования синхронизации. Это особенно полезно в многопоточных приложениях, где необходимо сохранять состояние для конкретного потока.
private static final ThreadLocal<DateFormat> dateFormat =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
void formatDate(Date date) {
System.out.println(dateFormat.get().format(date)); // У каждого потока свой экземпляр
}
▸ Избегает создания нового объекта для каждого вызова
▸ Гарантирует потокобезопасность без блокировок
public class SecurityContext {
private static final ThreadLocal<User> currentUser = new ThreadLocal<>();
public static void login(User user) {
currentUser.set(user);
}
public static User getCurrentUser() {
return currentUser.get();
}
public static void logout() {
currentUser.remove();
}
}
// В фильтре сервлета
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
SecurityContext.login((User) req.getAttribute("user"));
try {
chain.doFilter(req, res);
} finally {
SecurityContext.logout();
}
}
private static final ThreadLocal<Map<String, String>> cache =
ThreadLocal.withInitial(HashMap::new);
void processData(String key) {
if (!cache.get().containsKey(key)) {
cache.get().put(key, expensiveOperation(key));
}
System.out.println(cache.get().get(key));
}
⚠️ Опасности:
▸ Утечки памяти в пулах потоков (например, Tomcat)
▸ Неожиданное поведение при повторном использовании потоков
▸ Сложность отладки из-за неявной передачи данных
▸ Контекст пользователя в веб-приложениях
▸ Локальный кэш для тяжелых вычислений
▸ Параметры локали и форматирования дат
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤2🎉1
Лямбда-выражения на первый взгляд могут показаться чем-то сложным и загадочным, но на самом деле они просты и интуитивно понятны.
Лямбда-выражение — это лаконичный способ описания анонимной функции, которую можно передать в качестве параметра или сохранить в переменной для последующего использования.
Если говорить ещё проще, лямбда-выражение — это просто другой способ создания и реализации объекта определённого типа. Рассмотрим это на примере создания нового потока.
У класса
Thread есть конструктор:
public Thread(Runnable target) {
...
}
То есть в конструктор нужно передать объект типа
Runnable. До лямбда-выражений мы сделали бы так:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello World");
}
}).start();
Здесь мы создаём анонимный класс, реализующий интерфейс
Runnable, с определённым методом run.Если использовать лямбда-выражение, тот же код будет выглядеть следующим образом:
Runnable r = () -> System.out.println("Hello World");
new Thread(r).start();
Или проще:
new Thread(() -> System.out.println("Hello World")).start();
Лямбда-выражение заменяет собой анонимный класс, который раньше был бы необходим для реализации
Runnable. Лямбда-выражение может использоваться только там, где ожидается реализация функционального интерфейса — интерфейса с единственным абстрактным методом. А интерфейс
Runnable именно такой:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Функциональный интерфейс должен содержать только один абстрактный метод, чтобы компилятор мог точно определить, какой метод реализует лямбда-выражение. В противном случае возникли бы неоднозначности и ошибки.
#java #lambda #Runnable
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤5🔥2🤣2
throws. Обычно связаны с внешними ресурсами: файлами, сетью.
public void readConfigFile() {
try (FileInputStream file = new FileInputStream("config.txt")) {
int data = file.read();
System.out.println("Данные: " + data);
} catch (FileNotFoundException e) {
System.err.println("Файл не найден!");
} catch (IOException e) {
System.err.println("Ошибка ввода-вывода: " + e.getMessage());
}
}
RuntimeException. Не требуют обработки, сигнализируют о логических ошибках.
public void printLength(String text) {
if (text == null) throw new IllegalArgumentException("Строка не может быть null!");
System.out.println("Длина: " + text.length());
}
public int divide(int a, int b) {
if (b == 0) throw new ArithmeticException("Деление на ноль!");
return a / b;
}
1. Для checked используйте try или try-with-resources.
2. Для unchecked проверяйте входные данные.
3. Документируйте исключения через @throws.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13🤝3👍1
type Vehicle {
id: ID!
type: String!
modelCode: String!
}
type Query {
vehicles: [Vehicle!]!
}@Controller
public class VehicleController {
@QueryMapping
public List vehicles() {
return List.of(new Vehicle("1", "bus", "XYZ123"));
}
}
{
vehicles {
id
type
}
}{
"data": {
"vehicles": [{ "id": "1", "type": "bus" }]
}
}public interface VehicleRepo extends JpaRepository, QuerydslPredicateExecutor {}
org.springframework.boot
spring-boot-starter-graphql
com.querydsl
querydsl-jpa
1. Включите GraphiQL для интерактивных запросов.
2. Используйте @MutationMapping для мутаций.
3. Настройте кеширование через CacheControl.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤1
@Entity
@Audited
public class Post {
@Id @GeneratedValue
private Long id;
private String title;
private String slug;
}
public interface PostRepository extends JpaRepository, RevisionRepository { } 💠 Доступны методы findRevisions() и findLastChangeRevision() для получения истории изменений.🔻 Envers создает таблицы _AUD и REVINFO для хранения версий и метаданных. При изменениях данные копируются в _AUD с типом операции (INSERT, UPDATE, DELETE).
Пример использования:
for (Revision rev : postRepository.findRevisions(postId)) {
System.out.println("Версия " + rev.getRevisionNumber() + ": " + rev.getEntity());
} 1. Добавьте зависимости hibernate-envers и spring-data-envers.
2. Включите @EnableJpaAuditing в конфигурации.
3. Для расширенного аудита используйте @CreatedBy и @LastModifiedBy.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👌2
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public Mono getUser(@PathVariable Long id) {
return userRepository.findById(id);
}
@GetMapping("/{id}/orders")
public Flux getUserOrders(@PathVariable Long id) {
return userRepository.findById(id)
.flatMapMany(orderRepository::findByUser);
}
}
WebClient.create("http://service.com")
.get()
.uri("/data")
.retrieve()
.bodyToFlux(Data.class)
.subscribe(System.out::println); 1. Используйте WebFlux для микросервисов с высокой нагрузкой.
2. Комбинируйте с R2DBC для реактивного доступа к БД.
3. Избегайте блокирующих вызовов (JDBC, JPA) в реактивных цепочках.
Please open Telegram to view this post
VIEW IN TELEGRAM
💯6❤3👍3
1.
2.
3.
4.
implementation 'androidx.room:room-runtime:2.6.1'
annotationProcessor 'androidx.room:room-compiler:2.6.1'
implementation 'androidx.room:room-ktx:2.6.1'
@Entity(tableName = "users")
public class User {
@PrimaryKey(autoGenerate = true)
public int id;
@ColumnInfo(name = "name")
public String name;
@ColumnInfo(name = "age")
public int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
@Dao
public interface UserDao {
@Insert
void insert(User user);
@Query("SELECT * FROM users")
List getAllUsers();
@Delete
void delete(User user);
}
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}AppDatabase db = Room.databaseBuilder(context, AppDatabase.class, "database-name").build();
UserDao userDao = db.userDao();
// Получение LiveData-списка всех пользователей
@Query("SELECT * FROM users")
LiveData<List<User>> getAllUsers(); // LiveData<List<User>> - тип возвращаемого значения
userDao.getAllUsers().observe(this, users -> {
// Обновление интерфейса при изменении данных
});static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE users ADD COLUMN email TEXT");
}
};
AppDatabase db = Room.databaseBuilder(context, AppDatabase.class, "database-name")
.addMigrations(MIGRATION_1_2)
.build();1.
2.
3.
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertOrUpdate(User user);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤3
В Java 9 появилось два новых метода, полезных для выбора элементов потока с хорошей производительностью: takeWhile и dropWhile.
Допустим, у нас есть следующий список блюд:
List<Dish> specialMenu = Arrays.asList(
new Dish("seasonal fruit", 120),
new Dish("prawns", 300),
new Dish("rice", 350),
new Dish("chicken", 400),
new Dish("french fries", 530));
Для получения блюд с калорийностью меньше 320, можно воспользоваться операцией
filter. Недостаток операции filter в том, что она требует прохода в цикле по всему потоку данных с применением предиката ко всем элементам.В нашем примере список уже отсортирован по числу калорий. Вместо того, чтобы пройтись по каждому элементу, можно прекратить работу сразу же после обнаружения блюда, содержащего 320 калорий или более. В случае небольшого списка это может показаться не таким уж громадным преимуществом, но при работе с потенциально большим потоком элементов окажется весьма полезным.
Поможет нам в этом операция
takeWhile! Она позволяет выполнить срез любого потока данных (даже бесконечного) с помощью предиката. И, к счастью, она прекращает работу сразу же по обнаружении неподходящего элемента. Вот как ее следует использовать:
List<Dish> sliceMenu1
= specialMenu.stream()
.takeWhile(dish -> dish.getCalories() < 320)
.collect(toList());
#java #stream #takeWhile
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤2
public class Demo {
public static void workload(int a) {
System.out.println(a + 1); // Простая операция
}
public static void main(String[] args) {
for (int i = 0; i < 100_000; i++) workload(i);
}
}
java -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler Demo
import org.graalvm.polyglot.*;
public class Polyglot {
public static void main(String[] args) {
try (Context context = Context.create()) {
int result = context.eval("js", "Math.pow(2, 10)").asInt();
System.out.println(result); // 1024
}
}
}
native-image -jar app.jar
./app
1. Для мультиязычности добавьте org.graalvm.sdk.
2. Используйте @CEntryPoint для нативных методов.
3. Тестируйте производительность через jmh.
GraalVM позволяет запускать Python и Ruby внутри Java через Polyglot API.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
В Java существует несколько «типов» (форм) классов, каждый из которых решает свои задачи и обладает своими особенностями. Рассмотрим основные из них:
1. Топ-level класс
Класс, объявленный в собственном файле .java (или несколько в одном файле, но только один может быть
public).Когда используется: для большинства объектов предметной области.
2. Статический вложенный класс (static nested class)
Объявляется внутри другого класса с модификатором
static.Когда используется: чтобы логически сгруппировать вспомогательный класс и избежать загрязнения пакета; не требует ссылки на экземпляр внешнего класса.
3. Нестатический внутренний класс (inner class)
Нестатический класс внутри другого класса. Имеет неявную ссылку на экземпляр внешнего.
Когда используется: когда класс не имеет смысла отдельно от конкретного экземпляра внешнего класса.
4. Локальный класс (local class)
Объявляется внутри метода. Видим только внутри этого метода.
Когда используется: для единичной вспомогательной логики, зависящей от локальных переменных.
5. Анонимный класс (anonymous class)
Определяется прямо при создании объекта, без имени. Часто для реализации интерфейсов/абстрактных классов «на месте».
Когда используется: когда нужна «быстрая» одноразовая реализация интерфейса или абстрактного класса.
6. Абстрактный класс (abstract class)
Может содержать как реализованные, так и абстрактные (без реализации) методы; сам не может быть инстанцирован.
Когда используется: когда есть общая часть реализации для набора подклассов, но нужна возможность «заставить» их реализовать конкретные методы.
7. Финальный класс (final class)
Нельзя унаследовать.
Когда используется: чтобы зафиксировать поведение и запретить расширение (например, для безопасности).
8. Перечисление (enum)
Специальный вид класса для фиксированного набора констант; может содержать поля и методы.
Когда используется: для ограничения значений до заранее известных.
9. Запись (record) [Java 16+]
Лаконичная форма класса-носителя данных: автоматом генерируются конструктор,
equals(), hashCode(), toString().Когда используется: для неизменяемых DTO/Value-объектов.
10. Запечатанный класс (sealed class) [Java 17+]
Позволяет закрыть иерархию наследования: указать, какие классы могут расширять/реализовывать.
Когда используется: когда важно контролировать все возможные подклассы (например, при реализации «альгебраического типа»).
11. Аннотации (annotation types)
Специальный «интерфейс» с префиксом
@interface для метаданных.Когда используется: для декларации информации, обрабатываемой компилятором или фреймворками (например,
@Override, @Entity).Каждый из этих типов классов/типов в Java помогает структурировать код, задавая чёткие контракты, ограничивая использование и сокращая «бесполезный» шаблонный код.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤7🔥2
import java.util.Random;
import java.util.Scanner;
public class RockPaperScissors {
public static void main(String[] args) {
String[] options = { "Камень", "Ножницы", "Бумага" };
Random rnd = new Random();
Scanner sc = new Scanner(System.in);
int userScore = 0, compScore = 0;
System.out.println("Игра «Камень, ножницы, бумага». Введите 0-Камень, 1-Ножницы, 2-Бумага, q-выход.");
while (true) {
System.out.print("Ваш выбор: ");
String inp = sc.nextLine();
if (inp.equalsIgnoreCase("q")) break;
int user, comp = rnd.nextInt(3);
try {
user = Integer.parseInt(inp);
if (user < 0 || user > 2) throw new NumberFormatException();
} catch (NumberFormatException e) {
System.out.println("Некорректно, попробуйте снова.");
continue;
}
System.out.printf("Вы: %s, Компьютер: %s → ", options[user], options[comp]);
int outcome = (user - comp + 3) % 3;
// 0=ничья, 2=победа пользователя, 1=проигрыш
if (outcome == 0) {
System.out.println("Ничья");
} else if (outcome == 2) {
System.out.println("Вы выигрываете");
userScore++;
} else {
System.out.println("Проигрываете");
compScore++;
}
System.out.printf("Счёт %d:%d%n", userScore, compScore);
}
System.out.println("Игра окончена. Финальный счёт " + userScore + ":" + compScore);
sc.close();
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
😁14👍3😍3
Когда требуется конкатенировать строки с использованием
Stream, можно выбрать один из двух методов: Stream.reduce() или Stream.collect(Collectors.joining()).Пример с
Stream.reduce(): List<String> list = List.of("Str1", "Str2", "Str3");
String result = list.stream().reduce("", (a, b) -> a + b);
System.out.println(result); // Str1Str2Str3Пример с
Collectors.joining(): List<String> list = List.of("Str1", "Str2", "Str3");
String result = list.stream().collect(Collectors.joining());
System.out.println(result); // Str1Str2Str3Использование
reduce() для конкатенации строк не является оптимальным с точки зрения производительности. При каждом вызове операции +, создается новая строка, так как строки в Java неизменяемы. Это приводит к увеличению нагрузки на память из-за создания множества промежуточных объектов.В свою очередь, метод
Collectors.joining() использует StringBuilder для сборки строк, что значительно эффективнее. Он избегает создания лишних объектов и снижает потребление памяти.#java #Stream #reduce #joining
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤1
// Для импорта конкретного статического члена
import static package.Clazz.member;
// Для импорта всех статических членов класса
import static package.Clazz.*;
Пример:
public class MathUtils {
public static final double PI = 3.141592653589793;
public static int add(int a, int b) {
return a + b;
}
public static int subtract(int a, int b) {
return a - b;
}
}
import static MathUtils.PI;
import static MathUtils.add;
public class Main {
public static void main(String[] args) {
System.out.println("Value of PI: " + PI);
System.out.println("Addition result: " + add(5, 3));
}
}
import static MathUtils.*;
public class Main {
public static void main(String[] args) {
System.out.println("Value of PI: " + PI);
System.out.println("Addition result: " + add(5, 3));
System.out.println("Subtraction result: " + subtract(5, 3));
}
}
Плюсы: читаемость, компактность кода.
Минусы:
- не очевидно откуда берется поле или метод
- импорт всех статических членов может привести к конфликтам имен, если разные классы содержат статические члены с одинаковыми именами
#java #static #import
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥4❤1
Предположим, есть метод, который может выбросить
IOException и FileNotFoundException в какой последовательности должны идти блоки catch? Сколько блоков catch будет выполнено?Общее правило: обрабатывать исключения нужно от «младшего» к старшему. То есть нельзя поставить в первый блок
catch(Exception ex) {}, иначе все дальнейшие блоки catch() уже ничего не смогут обработать, так как любое исключение будет соответствовать обработчику catch(Exception ex).Таким образом, исходя из факта, что
FileNotFoundException extends IOException сначала нужно обработать FileNotFoundException, а затем уже IOException:
void method() {
try {
//...
} catch (FileNotFoundException ex) {
//...
} catch (IOException ex) {
//...
}
}
В Java 7 стала доступна новая языковая конструкция, с помощью которой можно перехватывать несколько исключений одним блоком
catch:
try {
//...
} catch(IOException | SQLException ex) {
//...
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤3🔥1
Исключения делятся на несколько классов, но все они имеют общего предка — класс
Throwable, потомками которого являются классы Exception и Error.Ошибки (Errors) представляют собой более серьёзные проблемы, которые, согласно спецификации Java, не следует обрабатывать в собственной программе, поскольку они связаны с проблемами уровня JVM. Например, исключения такого рода возникают, если закончилась память доступная виртуальной машине.
Исключения (Exceptions) являются результатом проблем в программе, которые в принципе решаемы, предсказуемы и последствия которых возможно устранить внутри программы. Например, произошло деление целого числа на ноль.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1