**
**
Самый полный набор вопросов для собеседования для крупных компаний в 2024 году. Монеты C не требуются. Нажмите здесь, чтобы загрузить или открыть полный набор вопросов для собеседования на веб-странице.
https://pan.quark.cn/s/865a0bbd5720
Инкапсуляция — это первый принцип ООП, который позволяет объектам скрывать детали своей внутренней реализации и предоставлять только интерфейс, к которому может получить доступ и который может использоваться внешним миром. В Java инкапсуляция достигается с помощью модификаторов доступа (например, частный, общедоступный, защищенный).
private
,чтобы скрыть детали его выбора.public
метод(нравитьсяgetterиsetter)предоставить доступ частным членами Исправлять。Наследование — это еще одна основная концепция ООП, которая позволяет одному классу (называемому подклассом или производным классом) наследовать свойства и методы другого класса (называемого родительским или базовым классом).
extends
**Ключевые слова:на Яве,ребенокдобрыйпроходитьextends
Ключевые слованаследоватьиз родительского класса。Полиморфизм — это третья основная концепция ООП, которая позволяет объектам разных классов отвечать на одно и то же сообщение, но конкретное поведение будет варьироваться в зависимости от фактического типа объекта.
на Яве,Перегрузкаи Переопределение — это две функции объектно-ориентированного программирования, связанные с методом,Все они позволяют существовать в классе нескольким методам с одним и тем же именем.,Но их значение и использование различны.
**
**
Перегрузка означает, что в одном классе можно определить несколько методов с одинаковым именем, но списки их параметров (тип и количество параметров) должны быть разными. Перегрузка — это проявление полиморфизма времени компиляции.
Перегрузкаиз Функции:
переписать означает предоставление метода в подклассе, который имеет точно такую же сигнатура метода, что и в родительском классе. переписать — это проявление Полиморфизма среды выполнения.
переписатьиз Функции:
final
**、**static
**или**private
**Блокировка метода:нравитьсяфруктыотецдобрыйсерединаизметодобъявляется какfinal
,тогда его нельзя будет использовать, переписав;нравитьсяфруктыобъявляется какstatic
,тогда вам нужно переобъявить его в подклассе, используя тот же модификатор,это называется прятаться;нравитьсяфруктыобъявляется какprivate
,тогда его нельзя будет использовать, переписав,Потому что частный метод не виден подклассам.Понимание разницы между перегрузкой и переопределением имеет решающее значение для правильного использования объектно-ориентированных функций Java, которые играют важную роль в разработке гибких и расширяемых иерархий классов.
**
**
Принцип единой ответственности (SRP) — важный принцип объектно-ориентированного проектирования. Он требует, чтобы у класса была только одна причина для его изменения. Другими словами, класс должен иметь только одну ответственность. Преимущество этого состоит в том, чтобы сделать дизайн класса более понятным, удобным в сопровождении и уменьшить влияние на другие классы.
Давайте проиллюстрируем принцип простым примером. единой ответственностиизотвечатьиспользовать。Предположим, мы разрабатываем систему управления студентами.,один из нихStudent
добрый Ответственный Указывает студентовизбазовыйинформация,Как показано ниже:
public class Student {
private String name;
private int age;
private String address;
// Конструктор、getterиsetterметодждать
}
этотStudent
добрый Ответственный Указывает студентовизбазовыйинформация,Укажите имя, возраст и адрес. Согласно принципу единой ответственности,Мы можем разделить его на отдельные классы,Каждый класс отвечает за свою ответственность. Например,мы можемк СоздайтеStudentInfo
добрый Приходить Ответственныйуправлятьстудентизбазовыйинформация,Как показано ниже:
public class StudentInfo {
private String name;
private int age;
private String address;
// Конструктор、getterиsetterметодждать // Другая информация, связанная с основной информацией о студентах
}
Разделив обязанности,Мы можем лучше управлять и расширить систему управления студентами. так,Когда нам нужно изменить логику обработки основной информации учащихся,Просто нужно ИсправлятьStudentInfo
добрый,не затрагивая другие классы.
Принцип открытости-закрытости (OCP) — это основной принцип разработки программного обеспечения. Он требует, чтобы программные объекты (классы, модули, функции и т. д.) были открыты для расширения и закрыты для модификации. Другими словами, мы должны расширять функциональность системы, добавляя новый код, а не изменяя существующий код.
Давайте проиллюстрируем принцип на примере открытости-закрытостиизотвечатьиспользовать。Допустим, у нас есть система обработки заказов.,один из нихOrder
добрый Ответственный Технологический заказодинизсоздаватьиплатить,Как показано ниже:
public class Order {
private String orderId;
private double amount;
private boolean isPaid;
// Конструктор、getterиsetterметодждать public void createOrder() {
// Логика создания заказов
}
public void makePayment() {
// Логика платежных поручений
}
}
Сейчас,Нам нужно добавить в заказ новую функцию: отправку покупателю письма с подтверждением. По принципу открытости-закрытости,我их Нетотвечать该прямойловить ИсправлятьOrder
добрыйизкод Приходитьвыполнитьэтотновый Функция,идаотвечать该проходить Расширять Приходитьвыполнить。мы можемк СоздайтеновыйсортOrderConfirmation
,Ответственный Логика отправки письма с подтверждением,Как показано ниже:
public class OrderConfirmation {
public void sendConfirmationEmail(String orderId) {
// Логика отправки письма с подтверждением
}
}
Таким образом, мы следуем принципу открытости-закрытости,проходить РасширятьOrderConfirmation
добрый Приходить Добавить письмо с подтверждением отправкииз Функция,и Нетда ИсправлятьOrder
добрыйизкод。
Принцип замены Лискова (LSP) — важный принцип объектно-ориентированного проектирования. Он требует, чтобы объекты подкласса могли заменять объекты родительского класса, не влияя на корректность программы. Другими словами, подкласс должен иметь возможность полностью заменить родительский класс и использоваться, не нарушая корректности программы.
Давайте проиллюстрируем Принцип на примере. замещения Рихтераизотвечатьиспользовать。Предположим, мыиметьодинграфикадобрыйизнаследоватьсистема,один из нихRectangle
добрый Представляет прямоугольник,Как показано ниже:
public class Rectangle {
protected int width;
protected int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int calculateArea() {
return width * height;
}
}
Сейчас,мы надеемсясуществоватьграфикадобрыйизнаследоватьсистемасерединадобавить водинновыйсортSquare
Представляет собой квадрат。в соответствии с Принцип замещения Рихтера,Мы должны гарантировать, что объект дочернего класса (квадрат) может заменить объект родительского класса (прямоугольник), не вызывая ошибок. Однако,нравитьсяфрукты我ихпрямойловить СоздайтеSquare
добрыйнаследоватьсRectangle
добрый,ипереписатьsetWidth
иsetHeight
метод,приведет к нарушению Принцип замещения Рихтера, потому что ширина и высота квадрата должны быть равны.
Чтобы следовать Принципу замещения Рихтера,Мы можем перепроектировать систему надзора,Например СоздайтеShape
добрыйделатьдляотецдобрый,Rectangle
иSquare
добрый分НенаследоватьShape
добрый,иобщийодинабстрактныйметодcalculateArea
,Как показано ниже:
public abstract class Shape {
public abstract int calculateArea();
}
public class Rectangle extends Shape {
protected int width;
protected int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
// getterиsetterметод
public int calculateArea() {
return width * height;
}
}
public class Square extends Shape {
protected int side;
public Square(int side) {
this.side = side;
}
// getterиsetterметод
public int calculateArea() {
return side * side;
}
}
Таким образом мы поддерживаем согласованность иерархии наследования и гарантируем, что объект подкласса (квадрат) может заменить объект родительского класса (прямоугольник), не вызывая ошибок.
Принцип инверсии зависимостей (DIP) — важный принцип объектно-ориентированного проектирования. Он требует, чтобы модули высокого уровня не зависели от модулей низкого уровня, но оба должны опираться на абстракции. Другими словами, мы должны разделить модули высокого уровня и модули низкого уровня посредством абстракции и полагаться на абстракцию, а не на конкретную реализацию.
Давайте проиллюстрируем принцип на примере инверсии зависимостейизотвечатьиспользовать。Допустим, мы разрабатываем систему обработки заказов.,один из нихOrderProcessor
добрый Ответственный Технологический заказодин,Как показано ниже:
public class OrderProcessor {
private Database database;
public OrderProcessor() {
this.database = new Database();
}
public void processOrder(Order order) {
// Логика обработки заказов
database.saveOrder(order);
}
}
В приведенном выше примере,OrderProcessor
добрыйпрямойловитьполагаться ВИнструменттелоизDatabase
добрый,в результате получаются модули высокого уровня(OrderProcessor
)с низкоуровневыми модулями(Database
)Существует тесная связь между。
Чтобы следовать принципу инверсии зависимостей,мы можемкпроходитьвести入абстрактный Приходитьразвязкамодуль высокого уровняимодуль низкого уровняизполагатьсясвязь。мы можемк СоздайтеабстрактныйизDatabase
интерфейс,позволятьOrderProcessor
добрыйполагаться В该интерфейси Нетда Инструменттеловыполнитьдобрый,Как показано ниже:
public interface Database {
void saveOrder(Order order);
}
public class OrderProcessor {
private Database database;
public OrderProcessor(Database database) {
this.database = database;
}
public void processOrder(Order order) {
// Логика обработки заказов
database.saveOrder(order);
}
}
public class MySQLDatabase implements Database {
public void saveOrder(Order order) {
// Логика сохранения заказов с использованием базы данных MySQL
}
}
public class OracleDatabase implements Database {
public void saveOrder(Order order) {
// Логика сохранения заказов с использованием базы данных Oracle
}
}
проходитьвести入абстрактныйизDatabase
интерфейс,Мы будем использовать модуль высокого уровня(OrderProcessor
)с низкоуровневыми модулями(Инструменттелоизбаза данныхвыполнитьдобрый)развязка,и полагается на абстракцию, а не на конкретные выборы. так,Мы можем легко переключаться между разными базами данныхвыполнить,вместо того, чтобыOrderProcessor
добрыйоказать влияние。
Принцип разделения интерфейсов (ISP) — важный принцип объектно-ориентированного проектирования, который требует, чтобы клиент не зависел от интерфейсов, которые ему не нужны. Другими словами, мы должны разделить большой интерфейс на маленькие интерфейсы и позволить клиенту полагаться только на те интерфейсы, которые ему нужны.
Давайте проиллюстрируем Принцип на примере. изоляции интерфейсаизотвечатьиспользовать。Предположим, у нас есть графический редактор,один из нихShape
интерфейс Представлять графику,Как показано ниже:
public interface Shape {
void draw();
void resize();
void rotate();
}
Сейчас,Мы хотим добавить новую функцию: цвет формы заливки. По принципу реализации интерфейса,Нам следует разделить большой интерфейс на маленькие интерфейсы.,Позвольте клиенту полагаться только на те интерфейсы, которые ему нужны. так,мы можемShape
интерфейс Разделить наDrawable
интерфейсиResizable
интерфейс,Как показано ниже:
public interface Drawable {
void draw();
}
public interface Resizable {
void resize();
}
public interface Shape extends Drawable, Resizable {
void rotate();
}
таким образом,мы будем большимиинтерфейсShape
Разделить на МаленькийинтерфейсDrawable
иResizable
,Позвольте клиентам зависеть только от тех интерфейсов, которые им нужны. так,Когда нам нужно добавить функцию заливки цветом,Просто нужнопозволятьграфикадобрыйвыполнитьDrawable
интерфейс Вот и все,Нет необходимости изменять существующий код.
Принцип повторного использования композиции (CRP) — важный принцип объектно-ориентированного проектирования. Он требует использования композиции объектов вместо наследования для достижения цели повторного использования кода. Другими словами, нам следует отдавать приоритет использованию композиции объектов для построения систем, а не слишком полагаться на наследование.
Давайте проиллюстрируем Принцип на примере. синтетического повторного использованияизотвечатьиспользовать。Допустим, мы разрабатываем игру,один из нихCharacter
добрый Указывает на игрусерединаиз Роль,Как показано ниже:
public class Character {
private Weapon weapon;
public Character() {
this.weapon = new Sword();
}
public void attack() {
weapon.use();
}
}
В приведенном выше примере,Character
добрыйпроходитьнаследоватьисоздавать Инструменттелоизоружиедобрый(Sword
)Приходитьвыполнить Функция атаки。Однако,Такой способ использования «наблюдать» может привести к трудностям при расширении и обслуживании системы.
Чтобы следовать Принципу синтетического повторного использования,мы можемкиспользоватьвернослонкомбинация Приходитьвыполнить Функция атаки。мы можемк СоздайтеWeapon
интерфейс,позволятьCharacter
добрыйкомбинацияодинвыполнить ПонятноWeapon
интерфейс
на Яве,Интерфейси Абстрактный класс — это инструменты для выбора абстрактных понятий в объектно-ориентированном программировании. Все они могут использоваться для определения набора абстрактных методов, эти методы могут быть представлены классом проверки (реализация Класс) или подкласс (Subclass) для калибровки (предоставьте конкретную выборку). Несмотря на их сходство, между ними есть некоторые ключевые различия:
implements
Ключевые слова Приходитьвыполнитьодинили Несколькоинтерфейс。public abstract
из,Не могу иметьметодтело。С Явы Начиная с версии 8, интерфейсы могут содержать метод по умолчанию (публичный с телом метода staticметод)истатическийметод。public static final
из,Это постоянно.extends
Ключевые слованаследоватьодинабстрактныйдобрый。implements
выполнитьинтерфейс,проходитьextends
наследоватьабстрактныйдобрый。При проектировании классов и интерфейсов выбор между использованием интерфейса или абстрактного класса обычно основывается на следующих принципах:
Выбор использования интерфейса или абстрактного класса зависит от конкретного сценария приложения и требований к проектированию. После Java 8, поскольку интерфейсы могут содержать методы по умолчанию с телами методов, это позволяет в определенных ситуациях использовать интерфейсы как более гибкие абстрактные типы.
В Java отношения обобщения и отношения реализации являются двумя основными концепциями объектно-ориентированного программирования. Они описывают различные методы соединения между классами, классами и интерфейсами.
Отношение обобщения обычно относится к отношению наследования, то есть один класс (подкласс или производный класс) наследует свойства и методы другого класса (родительского класса или базового класса). Эти отношения устанавливают отношения «есть-а».
Функции отношения обобщения:
Отношения реализации относятся к реализации класса одного или нескольких интерфейсов. Эти отношения устанавливают отношения «может быть» или «подобно».
выполнитьсвязьиз Функции:
extends
Ключевые словавыполнить,выполнитьсвязьпроходитьimplements
Ключевые словавыполнить。В практических приложениях отношения обобщения и отношения реализации часто используются вместе для создания гибких и масштабируемых систем. Выбор использования отношений обобщения или отношений реализации зависит от конкретных потребностей проекта и от того, как сбалансировать абстрактность и конкретность кода.
Java — статически типизированный язык, а это означает, что типы всех переменных необходимо определять во время компиляции. Java предоставляет два основных типа данных: базовый типиссылочный тип.
базовый тип — самый простой тип в Java данные, которые непосредственно соответствуют наименьшей единице данных компьютера. В Java имеется восемь типов базовых тип:
byte
, short
, int
, long
float
, double
char
boolean
ссылочный тип — это ссылки на объекты, они указывают на объекты в памяти. На Java, кроме базового Все, кроме типа, является ссылочным. тип,включатьдобрый、интерфейс、Массив и т. д.
целочисленный тип используется для представления целочисленных значений.,Их размер в памяти фиксирован. Например,int
добрыйформа占использовать4байты(32Кусочек),Может представлять целые числа от -2^31приезжать2^31-1.
int number = 10; // Правильное целочисленное присваивание
int largeNumber = 2147483647; // Назначение максимального значения
// int tooLargeNumber = 2147483648; // Присваивание вне диапазона приведет к ошибке компиляции.
тип с плавающей запятойиспользовать В表示иметь Маленькийчисло点изчислоценить。float
добрыйформа占использовать4байты,иdouble
добрыйформа占использовать8байты,Последнее обеспечивает большую точность.
float pi = 3.14f; // Назначение типа поплавка
double piDouble = 3.141592653589793; // Присвоение типа double
char
добрыйформаиспользовать В表示одинперсонажи,это занимает2байты。Тип персонаж представлен одинарными кавычками.
char letter = 'A'; // Тип Назначение персонажа
boolean
добрыйформаиспользовать В表示логикаценить,это Толькоиметьдва Может能изценить:true
иfalse
。
boolean isTrue = true; // Логический Присвоение типа
ссылочный тип — более продвинутая концепция в Java.,Они указывают на объекты в памяти. на Яве,Все объекты управляются посредством ссылок.
String name = "Java"; // Строка является ссылочным тип
на Яве,преобразование тип - это своего рода тип данные конвертируются в другой тип Процесс данных. Это может быть автоматическим (неявным) или явным (принудительным).
int number = 10;
long largeNumber = number; // Скрытыйпреобразование типов
в некоторых случаях,Когда в операциях участвуют значения разных типов,较Маленькийизтип данные автоматически преобразуются в больший тип данных, этот процесс называется Тип продвижения。
int number = 10;
double pi = 3.14;
double result = number / pi; // Результат - двойной тип
В реальном программировании выберите соответствующий тип данныхдляпроизводительностьи Управление памятьюключевой Тяжелыйхотеть。Например,Если вы знаете, что значение никогда не превысит 255,Такиспользоватьbyte
добрыйформавстреча Сравниватьиспользоватьint
Экономьте больше памяти。
byte smallNumber = 10; // Использовать тип байта
на Яве,базовый тип(primitive типы) и типы оберток (обертка типы) является обычной операцией. базовый тип — оригинальный тип Java данных, а тип упаковки — базовый тип инкапсуляции, это классы в пакете java.lang.
С Явы Начиная с 5 версии в Java появилась возможность распаковки автобоксов, что позволило использовать автозовый Типы могут автоматически конвертироваться между соответствующими типами упаковки.
базовый тип конвертируется в соответствующий тип упаковки.
Integer integerObject = 123; // intприжатезInteger автобокс
Упаковкапреобразование тип — соответствующий базовый тип。
int intValue = integerObject; // Integerприезжатьintиз Автоматическая распаковка
Хотя распаковка автобокса очень удобна, иногда приходится делать преобразование типа явно.
использовать УпаковкадобрыйформаизстатическийметодvalueOf()
Упаковка。
Integer integerObject = Integer.valueOf(123); // Явный бокс
использовать УпаковкадобрыйформаизxxxValue
метод Распаковка。
int intValue = integerObject.intValue(); // явная распаковка
NullPointerException
。equals()
метод。для浮点число,Из-за проблем с точностью,Будьте осторожны при выравнивании.Integer
добрыйиметьодинкэшмеханизм,Имеет целочисленные значения от -128приезжать127. При доступе к целочисленному значению в этом диапазоне,Собственно возвращает объект в кэш,Вместо того, чтобы каждый раз создавать новые объекты.public class BoxingUnboxingExample {
public static void main(String[] args) {
// автобокс
int num = 100;
Integer wrapper = num; // автобокс
// Автоматическая распаковка
int number = wrapper; // Автоматическая распаковка
// Явный бокс
Integer wrapper2 = Integer.valueOf(100);
// явная распаковка
int number2 = wrapper2.intValue();
// Используйте метод равенства()Сравнивать для переноса значений типа
Integer a = 10;
Integer b = 10;
Integer c = 200;
boolean areEqual = (a.intValue() == b.intValue()); // true
boolean areNotEqual = (a.equals(c)); // false
}
}
Понимание преобразования между базовым типом и обернутыми типами очень важно для написания правильных и эффективных программ на Java.
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
должен быть интернирован: задержан
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* jdk.internal.misc.VM class.
*/
/**
*кэш для поддержки семантики идентификации объектов для значений между автобоксами
*-128и127 (включительно), согласно требованиям JLS.
*
*кэш инициализируется при первом использовании. размер кэша
*может быть{@code-XX:AutoBoxCacheMax=<size>}Управление опциями。
*Во время инициализации виртуальной машины java.lang.Integer. IntegerCache.highсвойство
* Может быть настроен и сохранен в специальном системном свойстве.
*jdk.internal.misc. Класс ВМ.
*/
В Java-программировании,верноInteger
вернослонизсоздаватьииспользоватьдаобщийиз操делать。Однако,Многие застройщики могут не осознавать, что приезжать,проходитьдругойизметодсоздаватьInteger
вернослон,Механизм восстановления и его воздействие могут быть совершенно разными.
JavaдляInteger
добрыйпоставлять Понятноодинкэшбассейн,существоватьInteger.valueOf(int i)
методизвыполнитьсередина,Имеется внутренний кэш-механизм. Согласно спецификации автобокса Java,Integer.valueOf()
методвстречакэшот-128
приезжать127
в пределах досягаемостиизInteger
вернослон。
Integer.valueOf(int i)
изкэшлогика:int
ценитьсуществовать-128
приезжать127
между(включать-128
и127
),valueOf()
методвернеткэшизвернослон。int
ценитьвнеэтотобъем,valueOf()
метод Воля СоздайтеновыйизInteger
вернослон。new Integer(int i)
из ХОРОШОдля:int
ценитьда Что,new Integer(int i)
общийдавстреча СоздайтеновыйизInteger
вернослон Пример。использоватьInteger.valueOf()
и Нетдапрямойловитьиспользоватьnew
оператор может уменьшитьиспользование памятиисбор мусораизнакладные расходы,特Недакогда Обработка больших объемовInteger
вернослончас,В частности, их значения сосредоточены в вышеупомянутом кэш-диапазоне.
valueOf
иnew
изпроизводительностьpublic class IntegerCachingDemo {
public static void main(String[] args) {
int number = 127;
Integer i1 = new Integer(number);
Integer i2 = Integer.valueOf(number);
System.out.println("i1 == i2 ? " + (i1 == i2)); // выход правда, потому что valueOf возвращает объект кэша
int anotherNumber = 128;
Integer i3 = new Integer(anotherNumber);
Integer i4 = Integer.valueOf(anotherNumber);
System.out.println("i3 == i4 ? " + (i3 == i4)); // выход false, поскольку valueOf не имеет значения, создается новый объект кэша
}
}
Integer
вернослонpublic class IntegerLoopCreation {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 200; i++) {
// Используйте valueOf() для создания целочисленного объекта в диапазоне кэша.
list.add(Integer.valueOf(i));
// Использование new для создания целочисленного объекта создаст новый объект даже в пределах диапазона кэша.
list.add(new Integer(i));
}
}
}
на Яве,базовый типверноотвечатьизбуфербассейн主хотетьобратитесь киздаInteger
добрыйизкэшбассейн,потому чтодля Что他избазовый тип(нравитьсяint
, long
, double
ждать)и Нет Инструментиметьдобрыйпохожийизкэшмеханизм。этоткэшбассейнда Зависит отJavaвиртуальная машина(JVM)сдвигатьсяуправлятьиз,цельсуществоватьулучшатьпроизводительность,特Недасуществоватьсоздавать Многотакой же整числоценитьизInteger
вернослончас。
Integer
кэшбассейниз工делать Оригинал理:Integer.valueOf(int i)
иInteger.valueOf(String s)
методвстречакэшот-128
приезжать127
(включать-128
и127
)изInteger
вернослон。int
ценитьприезжатьInteger
вернослончас,Если значение находится в пределах кэша,будет использовать экземпляр в кэшпуле,и Нетдакаждый развызов Все Создайтеновыйизвернослон。Integer
вернослончас,Если объект является объектом в кэшпуле,Так Распаковканазадизint
ценить Воляпрямойловитьобратитесь к КэтоткэшизInteger
вернослон。Integer.valueOf(int i)
:нравитьсяфруктыпараметрi
существовать-128
приезжать127
между,этотметодвернетсякэшбассейнсерединаизInteger
вернослон。Integer.valueOf(String s)
:Волянитьпараметр Конвертироватьдляint
ценить,ивозвращатьсяверноотвечатьизInteger
вернослон,Также будет использоваться кэш-пул.Integer.valueOf()
из Что他Перегрузка Версия:нравитьсяловить受long
、float
、double
ждатьдобрыйформаизпараметр,Но они не будут использовать кэш-пул.Пул кэша в основном используется в следующих сценариях:
Integer
**Объект:Например,Поле идентификатора в операциях с базой данных,Или целое значение в элементе конфигурации.HashSet
、HashMap
ждать Класс коллекциичас,нравитьсяфруктыключилиценитьдаInteger
добрыйформа,Кэш-пул может уменьшить использование памяти и повысить производительность.Integer
вернослончас Всевстреча生成новыйиз Пример。public class IntegerCacheDemo {
public static void main(String[] args) {
Integer int1 = 123;
Integer int2 = 123;
System.out.println(int1 == int2); // выход false, потому что 123 находится вне диапазона кэш-пула
Integer int3 = Integer.valueOf(123);
Integer int4 = Integer.valueOf(123);
System.out.println(int3 == int4); // выход true, потому что valueOf использует кэш-пул
}
}
В этом примере,прямойловитьиспользоватьnew Integer(123)
создаватьиздвавернослонint1
иint2
Нет Взаимнождать,потому чтодляэтоихдадвадругойиз Пример。ииспользоватьInteger.valueOf(123)
создаватьиздвавернослонint3
иint4
Взаимнождать,Потому что они ссылаются на один и тот же экземпляр в кэш-пуле.
Понимая базовый типверноотвечатьизбуфербассейн,Разработчики могут лучше использовать возможности автобокса Java.,Пишите более эффективный и ресурсосберегающий код.
В Java-интервью,String
добрый Частыйда Интервьюеры любят обсуждатьиз Одна из тем,Потому что оно включает в себя не только основы приезжать на Java.,возвращатьсяипроизводительность Оптимизация тесно связана с。к Внизда Некоторый关ВString
из Тяжелыйхотеть Очки знанийа такжесуществоватьразработка проектасерединаотвечатькогдаизбегатьизошибка。
String
из Очки знаний на собеседовании:Строки являются константами; их значения не могут меняться после них.
*создавать. Строковые буферы поддерживают изменяемые строки.
*Поскольку объекты String неизменяемы, их можно использовать совместно.
String
вернослон一旦создавать,Его значение невозможно изменить.+
操делать符соединятьнитьвстречапривести кпроизводительностьвопрос,потому чтодлякаждый разцикл Всевстреча СоздайтеновыйизString
вернослон。рекомендоватьиспользоватьStringBuilder
илиStringBuffer
。equals()
метод:для строки сравненияизсодержаниеданет Взаимнождать。hashCode()
метод:возвращатьсянитьиз Хэшценить,Определяется содержимым строки.substring()
метод:возвращатьсянитьизребенок串。indexOf()
и lastIndexOf()
метод:分Невозвращатьсяобратитесь к定字符илиребенок串существоватьэтотнитьсерединапервыйибольшинствоназад一次出сейчасиз索вести。trim()
метод:去удалятьнить两конециз Пробелы。valueOf()
метод:Воля Что他вернослон Конвертироватьдлянить形式。split()
метод:в соответствии с分隔符分割нить。replace()
и replaceAll()
метод:分Не替换нитьсерединапервый出сейчасизи Местоиметьсоответствоватьизребенок串。toLowerCase()
и toUpperCase()
метод:Волянить Конвертироватьдля Маленький写иликапитал。isEmpty()
метод:исследоватьнитьданетдлянулевой。length()
метод:возвращатьсянитьиздлина。intern()
метод:Волянитьвернослони Пул строковых константа С сравнением, если строка уже существует в пуле констант, вернуть ссылку в пул констант на объект。new String("...")
**:этотвстречасоздавать Нет必хотетьизновыйнитьвернослон,ииспользоватьоригинальныйстроковый литерал Можеткпрямойловитьвестииспользовать Пул строковых Объекты в константе.==
**оператор:этотвстречаисследоватьссылка на объектданет Взаимнождать,и Нетданитьизсодержание。отвечать该использоватьequals()
метод。null
**исследовать:существоватьвызовнитьизметод До,отвечатьубеждатьсянить Нетдляnull
,кизбегатьNullPointerException
。String
** как ключ коллекции:потому чтоString
из Неизменяемость,это Нетчастоподходящий合делатьдлясобиратьизключ。нонравитьсяфрукты你использовать ПонятноодиннаследоватьсString
из Может变добрыйделатьдляключ,Тогда требование неизменности коллекции может быть нарушено.StringBuffer
**:StringBuffer
изметод Нетда Безопасность резьбыиз。существоватьэтотдобрый Состояние Вниз,отвечатьиспользоватьStringBuilder
(нравитьсяфруктынитьизобщий Нет Тяжелыйхотеть)илиReentrantLock
иAtomicReference
ждатьтакой же步механизм。String
** для хранения конфиденциальной информации:потому чтонитьна Яведак Хранится в виде открытого текстаиз,Информация может попасть в журналы, дампы кучи или отладки.String
**Выполнение операций, чувствительных к производительности.:Например,Нетхотетьсуществовать Многочисло据начальствоиспользоватьString
Выполнить поиск подстроки,Вместо этого рассмотрите возможность использования специализированной библиотеки.,Например, Apache Commons Lang.switch
**заявлениесерединаиспользовать**String
**:ХотяJava 7начинатьподдерживатьсуществоватьswitch
заявлениесерединаиспользоватьString
,Но в ситуациях, чувствительных к производительности,использоватьif-else
может быть более эффективным。String
**Внутреннее знание классов для оптимизации кода:Например,Полагайтесь на Неизменяемость строки, чтобы избежать синхронизации.,Это может привести к созданию кода, который будет сложно понять и поддерживать.проходитьверно ЭтиString
Взаимно关из Очки знанийиобщийизошибкаиметьглубокийпонимать,Можете продемонстрировать свое владение основами Java во время собеседований.,В то же время это также может улучшить качество кода при разработке проектов.
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/**
* The value is used for character storage.
*Это значение используется для хранения символов.
* @implNote This field is trusted by the VM, and is a subject to
* constant folding if String instance is constant. Overwriting this
* field after construction will cause problems.
*
* Additionally, it is marked with {@link Stable} to trust the contents
* of the array. No other facility in JDK provides this functionality (yet).
* {@link Stable} is safe here, because value is never null.
*/
@Stable
private final byte[] value;
/**
*{@code Класс String} представляет строку. все
*Строковые литералы в программах Java, такие как {@code "abc"},
*выполнить — пример данной категории.
</p>
*Строки являются константами; их значения не могут меняться после них.
*создавать. Строковые буферы поддерживают изменяемые строки.
*Поскольку объекты String неизменяемы, их можно использовать совместно.。Например
*<blockquote><pre>
*String str="abc";
*</pre></blockquote><p>
*Эквивалент:
*<blockquote><pre>
*char-data[]={'a','b','c'};
*String стр = новая строка (данные);
*</pre></blockquote><p>
*Вот еще несколько советов о том, как использовать строки:
*<blockquote><pre>
*System.out.println(“abc”);
*Строка cde="cde";
*System.out.println(“abc”+cde);
*String c = "abc".substring(2,3);
*String d=cde.substring(1,2);
*</pre></blockquote>
</p>
*Класс {@code String} включает метод для проверки
*Последовательность одиночных символов, для строки Сравнивать, для
* Поиск строки, извлечение подстроки и создание
* Копия строки, в которой все символы переведены в верхний регистр или
*нижний регистр. Отображение регистра основано на стандартной версии Unicode.
*По {@link java.lang.Character Символ} указан класс.
</p>
*Язык Java обеспечивает специальную поддержку строк.
*Оператор конкатенации(+&),использовать Виз Конвертировать
*Преобразуйте другие объекты в строки. Дополнительная информация о строках
*Подключайтесь и конвертируйте,Видеть<i>The Java&trade;языкспецификация</i>。
*
*<p>удалять Нет Другойиметьиллюстрировать,В противном случае это будет{@code null} параметр, передаваемый конструктору
* или метод приведет к {@link NullPointerException}
*Бросили.
*
*<p>{@code String} представляет строку в формате UTF-16.
*Чтосередина<em>Дополнительные персонажи</em>Зависит от<em>Представительство агента
*верно</em>(Видетьunicodeчасть
*{@код Character}добрыйсерединаизпредставление персонажа</a>
*Подробнее).
*Значение индекса относится к кодовой единице {@code-char}, поэтому оно добавляется
*Символы в {@code В String используются две позиции}.
*<p>{@code String} класс обеспечивает обработку
*Кодовые точки Unicode (т.е. символы) и
* Обрабатывает единицы кода Юникода (т. е. значения {@code-char}).
*
*<p>удалять Нет Другойиметьиллюстрировать,в противном случаедля строки сравненияизметод Не используйте локаль
*Принято к сведению. {@связь метод, предоставляемый классом java.text.Colletor}
* Детализированная, чувствительная к локали строка Сравнивать.
*
*@implNote Оператор конкатенации строк выборочно оставлен
*По усмотрению компилятора Java, если компилятор в конечном итоге соответствует
*приезжать<i>Java&trade;языкспецификация</i>。Например,{@code javac} компилятор
*Вы можете использовать {@code StringBuffer}、{@code String Builder}、{@codeStringBuffer}Приходитьвыполнитьоператор,
*или{@код java.lang.invoke.StringConcatFactory}, в зависимости от версии JDK. этот
* Преобразование строк калибровки обычно осуществляется с помощью метода {@code-toString},
* По {@code-Object}определению и всем классам Java на соответствие.
*
*@authorLee Boynton
*@authorАртур van Hoff
*@authorМартин Buchholz
*@authorUlf Zibis
*@См. java.lang.Object#toString()
*@См. java.lang.StringBuffer
*@См. java.lang.StringBuilder
*@См. java.nio.charset. Кодировка
*@С версии 1.0
*@jls 15.18.1Конкатенация строковый оператор+
*/
на Яве,Базовый тип данных(primitive types)самда Безопасность резьбы, потому что они неизменяемы. Это означает, что когда-то базовый тип После создания данных их значение невозможно изменить. Однако, когда несколько потоков совместно используют и изменяют одну и ту же базу Безопасность появится при обращении к данным резьбывопрос. Ниже приведен основной тип в Java. данных:
Это основы данныхизпеременнаяда Безопасность резьбы, поскольку их значения не могут быть изменены после присвоения. Но если у вас есть указатель на эти основные типы Ссылка на массив данных, и несколько потоков могут получить доступ к этому массиву, то этот массив не является Безопасностью. резьбы, потому что разные потоки могут независимо изменять разные элементы массива.
Кроме того, хотя базовый тип данныхсамда Безопасность потоки, но эти типы операций, связанных с перемещением (например, вычисления и обновления), могут привести к ошибке в безопасности в многопоточной среде. Проблемы с резьбами, особенно когда несколько потоков пытаются одновременно изменить одну и ту же переменную. Чтобы обеспечить безопасность резьбы,Может能需хотетьиспользоватьтакой же步код块、Замок、Атомарные переменные(нравитьсяAtomicInteger
)или Что他иконтроль волосмеханизм。
public class ThreadSafeExample {
private int counter = 0;
public void increment() {
counter++; // Неатомарная операция, которая может вызвать проблемы в многопоточной среде.
}
}
// правильныйиз Безопасность темы, способ использования атомарных классов
public class AtomicExample {
private AtomicInteger counter = new AtomicInteger(0);
public void increment() {
counter.incrementAndGet(); // Атомарные операции,Безопасность резьбы
}
}
В первом примере,хотяint
добрыйформасамда Безопасность резьбыиз,нодаcounter++
操делать Нетда Оригиналребенокиз,Это означает, что в многопоточных средах могут возникнуть условия гонки. Во втором примере,использоватьAtomicInteger
убеждаться ПонятноincrementAndGet()
操делатьиз Оригиналребеноксекс,Таким образом можно избежать проблемы безопасности резьбы.
Подводя итог, в основном данные сами по себе неизменны и, следовательно, Безопасность резьбыиз,Но при использовании этих типов переменных в многопоточной среде,Еще нужно обратить внимание на синхронизацию и управление параллелизмом.
@Override
@HotSpotIntrinsicCandidate
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
на Яве,String
、StringBuffer
иStringBuilder
да三добрыйдругойсорт,У них разные способы обработки строк. Вот их основные особенности:
String
вернослон一旦создавать,Его значение невозможно изменить.этот意味着任что Исправлять操делать ВсевстречапроизводитьодинновыйизString
вернослон。"hello"
)Проходитьчастохранилищесуществовать Пул строковых константа, это помогает экономить память.String
добрыйда Безопасность резьбыиз,потому чтодля Что状态не могуодеяло Изменять。String
、StringBuffer
иStringBuilder
StringBufferStringBuffer
вернослон Можеткодеяло Исправлять,Все операции модификации выполняются над одним и тем же объектом.,вместо создания новых объектов.StringBuffer
да Безопасность резьбыиз,Это означает, что его метод синхронизирован,Может использоваться в многопоточной среде.StringBuffer
существоватьодин Среда потокасередина СравниватьStringBuilder
медленный。StringBuffer
。StringBuffer
добрыйпохожий,StringBuilder
вернослон也Можеткодеяло Исправлять。StringBuilder
Нетда Безопасность резьбыиз,Его метод синхронизирован,Таким образом, производительность выше в однопоточной среде.StringBuilder
существоватьодин Среда потокасерединаизпроизводительностьлучше, чемStringBuffer
。StringBuilder
。StringBuilder
Проходитьчастодабольшинство佳выбирать,Потому что он предлагает лучшую производительность.StringBuffer
。String str1 = "Hello";
String str2 = str1 + " World"; // Создал новый объект String.
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World"); // Изменить исходный объект
StringBuilder sbd = new StringBuilder("Hello");
sbd.append(" World"); // Изменить исходный объект
В этом примере,использоватьString
руководить Конкатенация строкчас,каждый разсоединять操делать ВсевстречапроизводитьодинновыйизString
вернослон。иStringBuffer
иStringBuilder
则позволятьсуществовать Оригиналиметьвернослонначальстворуководить Исправлять,Избегает создания нескольких объектов.
выбиратьиспользоватьString
、StringBuffer
возвращатьсядаStringBuilder
取决ВИнструменттелоизотвечатьиспользоватьсцена:
String
,Когда вам нужен неизменяемый строковый объект,И когда содержимое строки не изменяется часто.StringBuffer
,Когда нужно выполнить Строковые операции в многопоточной среде,и Требовать Безопасность резьбычас。StringBuilder
,Когда вы выполняете Строковые операции в однопоточной среде,И при достижении производительности. /**
* Returns a canonical representation for the string object. Возвращает каноническое представление строкового объекта.
* <p>
* A pool of strings, initially empty, is maintained privately by the
* class {@code String}.
* <p>
* When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.
* <p>
* It follows that for any two strings {@code s} and {@code t},
* {@code s.intern() == t.intern()} is {@code true}
* if and only if {@code s.equals(t)} is {@code true}.
* <p>
* All literal strings and string-valued constant expressions are
* interned. String literals are defined in section 3.10.5 of the
* <cite>The Java™ Language Specification</cite>.
*
* @return a string that has the same contents as this string, but is
* guaranteed to be from a pool of unique strings.
* @jls 3.10.5 String Literals
*/
public native String intern();
на Яве,String.intern()
методдаодин Нетчасто Тяжелыйхотетьизхарактеристика,этои Пул строковых констант(String Pool)тесно связанный。к Внизда关ВString.intern()
методизподробный Очки знаний:
Пул строковых константдаJavaвиртуальная машина(JVM)использовать ПриходитьхранилищенитьпостоянныйипроходитьString.intern()
методпроизводитьизнитьиз Памятьокругдомен。Его главная Цельдадля Понятно节省Памятьнулевоймежду,Избегайте создания одного и того же строкового литерала несколько раз.
String.intern()
методString.intern()
методизделатьиспользоватьда Воляодиннитьвернослони Пул строковых константсерединаизнитьвернослонруководить Сравнивать。нравитьсяфруктыпостоянныйбассейнсередина Уже включено Понятно该нить,Возвращает ссылку на строковый объект в пуле констант, если нет;,Затем добавьте строковый объект в пул констант приезжать.,и возвращает ссылку на этот новый строковый объект.
public native String intern()
intern()
методдаString
добрыйизчленметод,Это местный метод,использоватьnative
Ключевые словалоготип,Это означает, что лежащая в его основе алгоритм написан на C/C++ или других языках, отличных от Java.
intern()
можно улучшитьпроизводительность,Потому что вы можете получить ссылку на строку непосредственно из пула констант."hello"
)создаватьизнить,Он будет автоматически помещен в Пуловые строки констант во время компиляции.new String("hello")
создаватьизнить,Не будет автоматически помещен в постоянный пул.,если явновызовintern()
метод。intern()
**методнакладные расходы**:нравитьсяфрукты Пул строковых константсередина Нетверноотвечатьизнить,intern()
методвстреча Волянитьдобавить вприезжатьпостоянныйбассейн,этот Может能с участием Некоторыйпроизводительностьнакладные расходы。intern()
**Может вызвать переполнение памяти.:нравитьсяфрукты无предел制地использоватьintern()
метод,Может привести к тому, что пул констант будет занимать много памяти.,Даже переполнение памяти.String s1 = "hello";
String s2 = new String("hello");
String s3 = s2.intern();
System.out.println(s1 == s2); // выход false
System.out.println(s1 == s3); // выход правда, потому что s3 вызов intern() После этого ссылка на пул констант "hello"
В этом примере,s1
прямойловитьпроходитьстроковый литералсоздавать,сдвигатьсяхранилищесуществовать Пул строковых константсередина。s2
проходитьnew String()
создавать,Нетвстречасдвигатьсяхранилищесуществоватьпостоянныйбассейнсередина。s3
проходитьвызовs2.intern()
После этого ссылка на пул константнитьвернослон。
String.intern()
**методдаодин Нетчастоиметьиспользоватьизхарактеристика,может помочь Оптимизировать использование строк。Однако,Разработчикам следует проявлять осторожность,Избегайте проблем с памятью, вызванных неправильным использованием. в некоторых конкретных сценариях,Например, при обработке большого количества одинаковых строк,Разумныйиспользовать**intern()
**Можеткприносить Приходитьпроизводительностьначальствоизпродвигать。**
В разных JVMвыполнить, Пул строковых Место хранения констант может отличаться, но в Oracle HotSpot JVM, например, претерпел несколько изменений во время своего развития:
new String()
создаватьизвернослон)дахранилищесуществоватьJavaкуча(Heap)серединаиз。кучадаJVMиспользовать Приходитьраспространятьиуправлятьвернослон Памятьизокругдомен。String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
В этом примере:
str1
иstr2
вестииспользоватьизда Пул строковых Тот же объект в константе.str3
даодинпроходитьnew
操делать符создаватьизновыйвернослон,Он расположен в куче Java.HotSpot — это популярная реализация виртуальной машины Java (JVM), широко используемая для запуска приложений Java. Он был разработан Sun Microsystems (теперь часть Oracle Corporation) и распространяется как часть Oracle JDK и OpenJDK. HotSpot VM известна своими технологиями оптимизации производительности, включая JIT-компилятор, сбор мусора и escape-анализ.
HotSpot VM использует несколько передовых технологий для обеспечения высокой производительности приложений Java, в том числе:
HotSpot VM был первым выбором для разработчиков Java с момента его запуска в 1997 году и продолжает развиваться и совершенствоваться по мере развития языка Java.
В HotSpot В JVM, Пул строковых Местоположение константы было изменено с постоянной генерации на зону методов и связано с метапространством. Понимание этих изменений помогает лучше понять управление JVM. Механизм памяти и помощь в настройке производительности и устранении неполадок.
Причина, по которой язык Java может занять место в сценариях приложений с чрезвычайно высокими требованиями к производительности, связана с JVM-компилятором JIT, механизмом сборки мусора и технологией escape-анализа. В этой статье будут подробно рассмотрены эти три технологии и показано, как они «за кулисами» оптимизируют производительность программ Java.
Код Java сначала компилируется в байт-код, а затем выполняется JVM. Роль JIT-компилятора заключается в компиляции «горячего» кода (часто выполняемого кода) в локальный машинный код во время выполнения, тем самым повышая эффективность выполнения.
Механизм сборки мусора Java отвечает за автоматическое управление памятью и переработку объектов, которые больше не используются, что позволяет избежать утечек памяти и проблем с дикими указателями.
Escape-анализ — это метод оптимизации JVM, который используется для определения того, выходит ли область действия объекта за пределы метода.
Ниже приведена простая программа на Java.,Показ метода горячей точки,Метод может быть оптимизирован JIT-компилятором.
public class HotspotExample {
public static void main(String[] args) {
int result = 0;
for (int i = 0; i < 10000000; i++) {
result += i;
}
System.out.println(result);
}
}
В этом примере, поскольку цикл выполняется достаточное количество раз, JIT-компилятор, скорее всего, скомпилирует тело цикла в оптимизированный машинный код.
JIT-компилятор, сборка мусора и escape-анализ — три волшебных оружия виртуальной машины Java для оптимизации производительности программы. Понимание их принципов и методов работы имеет решающее значение для написания эффективных программ на Java. Я надеюсь, что эта статья откроет вам путь к оптимизации производительности Java.
Код состояния HTTP 415 означает «Не поддерживается». Media Type”,Прямо сейчассервер无法处理просить附приноситьиз СМИтело Формат。этотошибка Проходитьчастопроисходитьсуществовать Клиент отправляетизпроситьсередина Включать Понятноодинсервер无法识Неили Не поддерживаетсяизContent-Type
голова。к Внизда Некоторый Может能привести кHTTP Причины ошибки 415:
Content-Type
**Неправильно:нравитьсяфрукты Клиент отправляетизпроситьсерединаContent-Type
голованастраиватьдлясервер Не поддерживаетсясортформа,Сравниватьнравитьсяapplication/xml
исервер期望издаapplication/json
,Это приведет к ошибке 415.Content-Type
Настройте правильно,Если формат данных в теле запроса не соответствует формату, ожидаемому сервером,Например, неправильный формат данных JSON.,Также выдает ошибку 415.Content-Type
заголовок ответа。Content-Type
,Или данные сериализуются неправильно перед отправкой тела запроса.Чтобы решить эту проблему, вы можете предпринять следующие шаги:
Content-Type
исервер期望сортформа Взаимносоответствовать。В справочных материалах упоминается, что HTTP встречается во время совместной отладки внешнего и внутреннего интерфейса. 415ошибкаиз Состояние,ипоставлять Понятно两добрыйразвязать决方案:назадконец Исправлятьивпередконец Исправлять❸❺。назадконец Исправлятьобратитесь киздаудалять@RequestBody
аннотация,впередконец Исправлятьобратитесь кизда Исправлятьпроситьчасизпросить头里Content-Type
добрыйформадляapplication/json
❸❺。
В Java-программировании,параметрпередачадаметодвызовизосновноймеханизм,Он определяет, как данные доставляются в метод и как метод получает и обрабатывает эти данные. Глубокое понимание передачи параметров,для编写Эффективный、Безопасностьи Может维护изкодключевой Тяжелыйхотеть。Эта статья познакомит вас Передача параметров Мир Java и изучение механизмов, лежащих в его основе. практики。
на Яве,методизпараметрпередача主хотетьиметь两добрый形式:Передача по значениюипередать по ссылке。
В Java 5 появились функции автоупаковки и распаковки, которые особенно полезны при передаче параметров.
public class AutoboxingExample {
public static void main(String[] args) {
Integer integer = 100;
increment(integer);
System.out.println(integer); // выход 101
}
static void increment(Integer n) {
n = n + 1;
}
}
Оценка параметров выполняется перед вызовом метода, что означает, что выражения параметров оцениваются до вызова метода.
public class ArgumentEvaluationExample {
public static void main(String[] args) {
int counter = 0;
performActions(incrementCounter(), counter);
}
static int incrementCounter() {
return ++counter;
}
static void performActions(int a, int b) {
// ...
}
}
В этом примере,counter
существоватьметодвызов Доодеяло Увеличивать Понятнодважды,Потому что порядок вычисления параметров неизвестен.
Java позволяет методам принимать переменное количество параметров, что очень полезно на практике.
public class VarargsExample {
public static void printArgs(Object... args) {
for (Object obj : args) {
System.out.println(obj);
}
}
public static void main(String[] args) {
printArgs("Hello", 123, 45.67);
}
}
При перегрузке методов тип и количество параметров являются ключом к различению разных методов.
public class MethodOverloadingExample {
int add(int a, int b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
public static void main(String[] args) {
// вызовдругойизaddметод
}
}
Передача параметров — это базовая концепция программирования на Java, которая напрямую связана с производительностью и поведением программы. Понимание разницы между передачей по значению и передачей по ссылке, а также освоение расширенных функций, таких как автоупаковка, распаковка, переменные параметры и перегрузка методов, имеют решающее значение для того, чтобы стать отличным разработчиком Java.
На языке программирования Java,Числа с плавающей запятой используются везде.,Будь то научные вычисления, рендеринг графиков или финансовый анализ и т. д.,float
иdouble
добрыйформа Все Играя Тяжелыйхотеть Роль。Однако,Между ними существует разница в точности и Сценариях использования.,понимать Этиразницадля编写Эффективный且准确из程序ключевой Тяжелыйхотеть。В этой статье будет подробно рассмотреноfloat
иdouble
из精度характеристика、Сценарии использованияа такжелучшие практики。
Числа с плавающей запятой — это стандарт арифметики двоичных чисел с плавающей запятой, основанный на стандарте IEEE 754, который определяет метод хранения и правила работы чисел с плавающей запятой.
потому чтоdouble
Сравниватьfloat
иметь Дажемногоизцифры мантиссы,потому чтоэтотdouble
из精度Даже高,Может представлять более широкий диапазон значений,Десятичные дроби также можно представить более точно.
public class FloatVsDouble {
public static void main(String[] args) {
float f = 1.123456789f;
double d = 1.123456789d;
System.out.println("Float: " + f); // выход Float: 1.1234568
System.out.println("Double: " + d); // выход Double: 1.123456789
}
}
В этом примере,потому чтоfloat
из精度предел制,Некоторые числа после запятой округляются.
float
Можно сохранить память,А человеческий глаз не чувствителен к нюансам точности.double
。На некоторых старых аппаратных платформах,float
运算Может能Сравниватьdouble
Вычисляйте быстрее,потому чтодляfloat
из操делать Даже简один。носуществоватьсейчас代处理器начальство,Между ними нет большой разницы в производительности.
BigDecimal
。В Java-программировании,Инкапсуляция — это основной принцип объектно-ориентированного программирования. Инкапсуляция означает сокрытие внутреннего состояния и поведения объекта.,Доступ к внешнему миру только через общедоступный интерфейс. Однако,В реальном развитии,Мы часто видим поля некоторых классов, объявленные как общедоступные. Кажется, это нарушает принцип инкапсуляции.,Так почему же поля никогда не должны быть общедоступными? В этой статье будет рассмотрен этот вопрос,И предоставьте некоторые лучшие практики.
Инкапсуляция — один из четырех основных принципов объектно-ориентированного программирования. Он имеет следующие ключевые моменты:
Хотя общедоступные поля могут упростить доступ, они также создают ряд проблем:
Чтобы поддерживать инкапсуляцию, мы должны следовать следующим инструкциям:
@Getter
и@Setter
ждатьLombokаннотация,Может автоматически генерировать метод getterиsetter.,Сократите шаблонный код.Хотя в некоторых ситуациях общедоступные поля могут показаться удобными, в долгосрочной перспективе они нарушают инкапсуляцию и делают ваш код более связанным и трудным в обслуживании. Поэтому, как старшие архитекторы Java, мы должны придерживаться частных полей и предоставлять доступ к этим полям через общедоступные средства доступа. Это не только сохраняет код чистым и удобным в сопровождении, но также обеспечивает гибкость для возможных будущих изменений. Помните, что инкапсуляция является краеугольным камнем объектно-ориентированного программирования, и мы всегда должны стремиться поддерживать и обеспечивать соблюдение этого принципа.
В объектно-ориентированном мире Java абстрактные классы и интерфейсы являются краеугольным камнем построения гибких и расширяемых архитектур. Они обеспечивают мощную поддержку повторного использования кода, разделения и полиморфизма. Однако между абстрактными классами и интерфейсами существуют очевидные различия в концепциях и использовании, а также существуют определенные связи. В этой статье будут рассмотрены различия и связи между абстрактными классами и интерфейсами, а также способы сделать правильный выбор в зависимости от потребностей проекта.
Абстрактный класс — это класс, экземпляр которого не может быть создан напрямую. Обычно он существует как базовый класс для других классов, предоставляя некоторые общие свойства и реализации методов, сохраняя при этом некоторые абстрактные методы для реализации подклассов.
public abstract class Animal {
public void eat() {
System.out.println("Eating");
}
public abstract void sound();
}
class Dog extends Animal {
public void sound() {
System.out.println("Woof");
}
}
Интерфейс — это совершенно абстрактное понятие, которое не обеспечивает никакой реализации и лишь определяет сигнатуру набора методов.
public interface UsbDevice {
void connect();
void disconnect();
default void status() {
System.out.println("Device status is OK");
}
}
class Smartphone implements UsbDevice {
public void connect() {
System.out.println("Connecting to USB");
}
public void disconnect() {
System.out.println("Disconnecting from USB");
}
}
public
,В абстрактных классах может быть много типов методов.абстрактныйдобрыйиинтерфейсдаJavaДлявернослондизайнсередина Нет Можетилинедостатокизчасть。этоих各симетьуникальныйизиспользоватьи Преимущества,Понимание их различий и взаимосвязей имеет решающее значение для разработки гибких, удобных в обслуживании систем.
на Яве,super
Ключевые словадаодин Нетчасто Тяжелыйхотетьизконцепция,этоиспользовать Ввестииспользоватькогдавпередвернослонизотецдобрыйвернослон。super
Ключевые словасуществоватьнаследоватьи Полиморфизмизначальство Вниз文середина Играя关ключ Роль。В этой статье подробно разберемсяsuper
Ключевые словаиз Сценарии использование связанных очков знаний.
в подклассе,Если вам нужна ссылка на членов родительского класса (включая метод, переменную и конструктор),Можеткиспользоватьsuper
Ключевые слова。
class Parent {
int value = 10;
}
class Child extends Parent {
void display() {
System.out.println(super.value); // выход Значение переменной родительского класса
}
}
class Parent {
void display() {
System.out.println("Parent display()");
}
}
class Child extends Parent {
void display() {
super.display(); // вызовотецдобрыйизметод
System.out.println("Child display()");
}
}
В конструкторе подкласса,Можеткиспользоватьsuper
Ключевые слова Вызов конструктора родительского класса。
class Parent {
Parent() {
System.out.println("Parent Constructor");
}
}
class Child extends Parent {
Child() {
super(); // Вызов конструктора родительского класса
System.out.println("Child Constructor");
}
}
в подклассепереписатьотецдобрыйизметодчас,нравитьсяфрукты需хотеть В методе подклассавызовотецдобрыйизвыполнить,Можеткиспользоватьsuper
Ключевые слова。
class Parent {
void display() {
System.out.println("Parent display()");
}
}
class Child extends Parent {
void display() {
super.display(); // вызовотецдобрыйизdisplay()метод
System.out.println("Child display()");
}
}
Когда переменные-члены подкласса имеют то же имя, что и переменные-члены родительского класса.,Переменные подкласса скроют переменные родительского класса. в это время,Если вам нужно получить доступ к переменной с тем же именем родительского класса,Можеткиспользоватьsuper
Ключевые слова。
class Parent {
int value = 10;
}
class Child extends Parent {
int value = 20;
void display() {
System.out.println(super.value); // выход Значение родительского класса
}
}
super
Ключевые словаиспользовать ВСсылка на членов родительского класса,иthis
Ключевые словаиспользовать Ввестииспользоватькогдавпередвернослонизчлен。в конструкторе,this
использовать Ввызовкогдавпереддобрыйиз Что他Конструктор,иsuper
использовать ВВызов конструктора родительского класса。
class Parent {
Parent() {
System.out.println("Parent Constructor");
}
}
class Child extends Parent {
Child() {
this(10); // вызовкогдавпереддобрыйиз Другойодин Конструктор
System.out.println("Child Constructor");
}
Child(int value) {
super(); // Вызов конструктора родительского класса
System.out.println("Child Constructor with value: " + value);
}
}
super
Ключевые слована Яведаодин Нетчасто Тяжелыйхотетьизконцепция,этопоставлять Понятноверноотецдобрыйчленизпрямойловитьдоступ。правильныйиспользоватьsuper
Ключевые словаможет помочь我их编写出Даже加прозрачный、Может维护изкод。делатьдляпередовойJavaАрхитектор,мы должны глубоко понятьsuper
из Сценарии использованияилучшие практики,так что В реальном развитии Даже加иметь Эффективно и географически выгодноиспользоватьэтот一характеристика。
на Яве,super
Ключевые словасуществовать Полиморфизмизначальство Вниз文середина Проходитьчастоиспользовать Ввызовотецдобрыйизметодвыполнить,Даже у подкласса переписать есть этот метод. Это особенно полезно в случае полиморфизма.,Потому что подклассы могут предоставлять свои собственные методы заполнения.,иsuper
Ключевые словапозволятьребенокдобрыйсуществовать需хотетьчасвызовотецдобрыйизметод。
В Java полиморфизм достигается за счет наследования и переопределения методов. Когда подкласс наследует родительский класс, он может переопределить методы родительского класса, чтобы обеспечить свою собственную реализацию. Однако в некоторых случаях подклассу может потребоваться вызвать метод родительского класса в своей собственной реализации метода, чтобы сохранить или улучшить поведение родительского класса.
super
вызовотецдобрыйметодВ методе подкласса,Можеткпроходитьsuper
Ключевые словавызовотецдобрыйизметод。этот Проходитьчастосуществоватьребенокдобрый需хотетьсуществоватьссебяизвыполнитьсерединаиспользоватьотецдобрыйметодиз ХОРОШОдлячасиспользовать。
class Animal {
public void makeSound() {
System.out.println("Some sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
super.makeSound(); // вызовотецдобрыйизmakeSoundметод
System.out.println("Bark");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.makeSound(); // выход: Some sound Bark
}
}
В приведенном выше примере,Dog
добрыйпереписать ПонятноAnimal
добрыйизmakeSound
метод。существоватьDog
добрыйизmakeSound
методсередина,первыйвызов Понятноsuper.makeSound()
Приходить执ХОРОШОотецдобрыйизmakeSound
метод,Затем добавил свое собственное поведение.
super
и Конструкторв конструкторе,super
Ключевые словаиспользовать ВВызов конструктора родительского класса. Это связано с тем, что при создании объекта подкласса необходимо сначала инициализировать часть родительского класса. Если конструктор подкласса явно не указывает конструктора родительского класса,Javaкомпиляторвстречасдвигаться插入верно Нет женьшеня Конструкторизвызов。нравитьсяфруктыотецдобрый Нет Нет женьшеня Конструктор,ребенокдобрыйдолженв конструктореиспользоватьsuper
Приходить Вызов конструктора родительского класса。
class Animal {
public Animal() {
System.out.println("Animal is created");
}
}
class Dog extends Animal {
public Dog() {
super(); // Вызов конструктора родительского класса
System.out.println("Dog is created");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
// выход: Animal is created
// выход: Dog is created
}
}
В этом примере,Dog
добрыйиз Конструкториспользоватьsuper()
вызов ПонятноAnimal
добрыйиз Конструктор。
super
Ключевые словасуществовать Полиморфизмсерединаиспользовать Ввызовотецдобрыйизметоди Конструктор。этопозволятьребенокдобрыйсуществоватьссебяизметодвыполнитьсерединабронироватьили Усиливатьотецдобрыйиз ХОРОШОдля。правильныйиспользоватьsuper
да Реализация полиморфизмаи维护кодпрозрачныйсексиз Тяжелыйхотетьчасть。существоватьдизайндобрыйиметодчас,следует рассматриватьприезжатьчточасиспользоватьsuper
Приходитьвызовотецдобрыйизвыполнить,Чтобы обеспечить ремонтопригодность кода.
В мире Java есть две очень похожие, но совершенно разные концепции — Override и Overload. Они как братья-близнецы, со схожими именами, но совершенно разными характерами. Сегодня давайте вместе раскроем их тайны и посмотрим, как они творят чудеса в волшебном мире Явы.
Переопределение, также известное как переопределение метода, является очень важной концепцией в объектно-ориентированном программировании. Это позволяет подклассам предоставлять свою собственную реализацию для замены методов родительского класса. Это похоже на магическую дуэль. Подкласс демонстрирует свою уникальную магию, переопределяя методы родительского класса.
class Animal {
public void makeSound() {
System.out.println("Some sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Bark");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.makeSound(); // выход: Bark
}
}
В этом примере,Dog
добрыйпереписать ПонятноAnimal
добрыйизmakeSound
метод,когдасоздаватьDog
вернослонивызовmakeSound
методчас,встреча执ХОРОШОDog
добрыйсерединаизвыполнить,и НетдаAnimal
добрыйсерединаизвыполнить。
Перегрузка, также известная как перегрузка метода, означает, что в одном классе может существовать несколько методов с одинаковым именем, если их списки параметров различаются. Это похоже на пир, где одно и то же блюдо может приобретать разные вкусы в зависимости от разных ингредиентов и способов приготовления.
class Calculator {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(1, 2)); // выход: 3
System.out.println(calc.add(1.5, 2.5)); // выход: 4.0
System.out.println(calc.add(1, 2, 3)); // выход: 6
}
}
В этом примере,Calculator
добрыйиметьтриadd
метод,этоихиз Список параметров другой,потому чтоэтот Можетксосуществовать。когдавызовadd
методчас,компиляторвстречав соответствии свходящийизпараметрдобрыйформаиколичестворешатьвызов Которыйметод。
Хотя и переопределение, и перегрузка связаны с именем метода, их суть различна:
конечно. переписать (переопределить) и перегрузить (перегрузить) — две очень важные концепции в Java, и в разных сценариях они применяются по-разному. Ниже я проиллюстрирую их Сценарии использования конкретными примерами.
Переопределение часто используется для достижения полиморфизма, когда подкласс может предоставить свою собственную реализацию для замены метода в родительском классе. Это очень часто встречается в отношениях наследования, особенно при проектировании фреймворков и библиотек.
Сценарий 1: Конструкция рамы
Предположим, мы разрабатываем среду графического пользовательского интерфейса (GUI).,один из нихButton
добрый,этоиметьодинdraw
методиспользовать Врисоватькнопка。Сейчас我их想хотеть СоздайтеImageButton
добрый,этонаследоватьсButton
добрый,ипереписатьdraw
метод Приходитьрисоватьодинприноситьиметькартинаизкнопка。
class Button {
public void draw() {
System.out.println("Drawing a simple button.");
}
}
class ImageButton extends Button {
@Override
public void draw() {
System.out.println("Drawing an image button with an image.");
}
}
public class Main {
public static void main(String[] args) {
Button button = new Button();
ImageButton imageButton = new ImageButton();
button.draw(); // выход: Drawing a simple button.
imageButton.draw(); // выход: Drawing an image button with an image.
}
}
В этом примере,ImageButton
добрыйпереписать ПонятноButton
добрыйизdraw
метод,Чтобы обеспечить конкретные возможности.
Сценарий 2: Расширение библиотеки
При использовании сторонних библиотек нам может потребоваться расширить функциональность классов в библиотеке. Переписывание позволяет сделать это, не нарушая существующую функциональность библиотеки.
class LibraryClass {
public void performAction() {
System.out.println("Performing a default action.");
}
}
class ExtendedClass extends LibraryClass {
@Override
public void performAction() {
System.out.println("Performing an extended action.");
}
}
public class Main {
public static void main(String[] args) {
LibraryClass libraryInstance = new LibraryClass();
ExtendedClass extendedInstance = new ExtendedClass();
libraryInstance.performAction(); // выход: Performing a default action.
extendedInstance.performAction(); // выход: Performing an extended action.
}
}
В этом примере,ExtendedClass
переписать ПонятноLibraryClass
изperformAction
метод,для обеспечения дополнительного функционала.
Перегрузка позволяет нам создавать несколько методов с одинаковым именем в одном классе, если их списки параметров различаются. Это очень полезно для обеспечения гибкости и удобства.
Сцена 1: Разнообразие методов использования
Предположим, мыиметьодинcalculate
метод,Он может выполнять различные вычисления на основе разных параметров.
class Calculator {
public int calculate(int a, int b) {
return a + b;
}
public double calculate(double a, double b) {
return a + b;
}
public int calculate(int a, int b, int c) {
return a + b + c;
}
}
public class Main {
public static void main(String[] args) {
Calculator calculator = new Calculator();
System.out.println(calculator.calculate(1, 2)); // выход: 3
System.out.println(calculator.calculate(1.5, 2.5)); // выход: 4.0
System.out.println(calculator.calculate(1, 2, 3)); // выход: 6
}
}
В этом примере,calculate
метододеяло Перегрузка Понятнотри раза,для размещения различных типов и величин параметров.
Сценарий 2: Перегрузка конструктора
Перегрузка конструктора позволяет нам создавать объекты на основе разных списков параметров.
class Person {
private String name;
private int age;
public Person(String name) {
this.name = name;
this.age = 0;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
Person person1 = new Person("Alice");
Person person2 = new Person("Bob", 30);
}
}
В этом примере,Person
добрыйиметьдва Конструктор,Принимается один параметр,Другойодинловить受двапараметр。этотпозволять我ихв соответствии с需хотетьсоздаватьPerson
вернослон。
на Яве,@HotSpotIntrinsicCandidate
аннотациядаJDKИсходный кодсерединаиспользоватьизодинособенныйаннотация,Это связано с внутренним механизмом оптимизации виртуальной машины HotSpot. Цель этой аннотации — указать, что определенные инструкции в виртуальной машине HotSpot могут быть оптимизированы для инструкций, специфичных для ЦП.,отиулучшатьпроизводительность。
Конкретно,когдаодинметододеялоотметкадля@HotSpotIntrinsicCandidate
час,Это указывает на то, что метод может иметь эффективную выборку.,Эта настройка основана на конкретном наборе инструкций ЦП. во время выполнения,HotSpotвиртуальная машинавстречапытатьсяиспользовать Эти Эффективныйизвыполнить Приходитьстандарт заменыизJavaметодвызов,уменьшитьметодвызовизнакладные расходы и повысить эффективность исполнения.
Например,String
добрыйсерединаизindexOf
метод Сразудаодинодеялоотметкадля@HotSpotIntrinsicCandidate
изметод。когдавызовString.indexOf
методчас,Если входящая строка содержит только символы Latin1,Виртуальная машина HotSpot может использовать специфичную для ЦП калибровку для выполнения этого метода.,Вместо использования интерпретатора байт-кода Java для выполнения.
Следует отметить, что,Хотяметододеялоотметкадля@HotSpotIntrinsicCandidate
,Но это не значит, что данная оптимизация будет использоваться во всех случаях. на самом деле,Происходит ли такая оптимизация, зависит от множества факторов.,Включая версию JVM, конфигурацию среды выполнения, конкретную аппаратную платформу и т. д. также,Несмотря на тометододеялоотметкадля@HotSpotIntrinsicCandidate
,На уровне интерпретатора (Interpreter) такой оптимизации тоже нет.
В итоге,@HotSpotIntrinsicCandidate
аннотациядаJavaсерединаиспользовать Вобратитесь к示метод Может能одеялоHotSpotвиртуальная машинаоптимизацияизодинотметка,Это помогает повысить эффективность выполнения конкретного метода.,ноэтотдобрыйоптимизацияданетдействительныйпроисходитьвозвращаться需хотетьучитывать Инструменттелоиз运ХОРОШОчассредаисостояние❷❸❹。
на Яве,отметкадля@IntrinsicCandidate
изметод Проходитьчастодаобратитесь к那些В HotSpotвиртуальная машинасередина Может能одеялооптимизациядляидентификация ВCPUизобратитесь к令изметод。Этиметод Проходитьчастода Некоторый Нетчасто基础且частоодеяловызовиз操делать,нравитьсябазовый Арифметические операции типа, Операции с массивамиждать。проходить Воля Этиметодотметкадля@IntrinsicCandidate
,Виртуальную машину HotSpot можно настроить во время выполнения в соответствии с конкретной аппаратной платформой и JVM.,выбиратьданетиспользоватьидентификацияизоптимизациявыполнить Приходитьстандарт заменыизJavaметодвызов。
к Внизда Некоторыйобщийизодеялоотметкадля@IntrinsicCandidate
изметод:
int
иlong
добрыйформаиздобавление、Вычитание、Умножение и деление и т.д.System.arraycopy()
метод,Он используется для эффективного копирования массивов.String
добрыйсерединаизcharAt()
、length()
ждатьметод。Math
добрыйсерединаизsin()
、cos()
、sqrt()
ждатьметод。Object
добрыйсерединаизhashCode()
、equals()
ждатьметод。Следует отметить, что,Хотяметододеялоотметкадля@IntrinsicCandidate
,Но это не значит, что данная оптимизация будет использоваться во всех случаях. на самом деле,Происходит ли такая оптимизация, зависит от множества факторов.,Включая версию JVM, конфигурацию среды выполнения, конкретную аппаратную платформу и т. д. также,Несмотря на тометододеялоотметкадля@IntrinsicCandidate
,На уровне интерпретатора (Interpreter) такой оптимизации тоже нет.
В итоге,@IntrinsicCandidate
аннотациядаJavaсерединаиспользовать Вобратитесь к示метод Может能одеялоHotSpotвиртуальная машинаоптимизацияизодинотметка,Это помогает повысить эффективность выполнения конкретного метода.,ноэтотдобрыйоптимизацияданетдействительныйпроисходитьвозвращаться需хотетьучитывать Инструменттелоиз运ХОРОШОчассредаисостояние➊❷❸❹❺❻。
В Java для просмотра того, какие методы оптимизированы, часто требуется использование определенных инструментов и методов. Поскольку JIT-компилятор Java оптимизирует «горячий» код во время выполнения, трудно увидеть, какие методы оптимизируются во время выполнения. Однако существуют инструменты и методы, которые могут помочь нам понять, какие методы можно оптимизировать:
-XX:+PrintCompilation
параметр МожетксуществоватьJVM运ХОРОШОчас打印出компилироватьизметодинформация。-XX:+PrintCompilation
Генерация параметров),Предоставляет графический интерфейс, позволяющий увидеть, какой метод был скомпилирован.,И тип и причина компиляции.-XX:+PrintInlining
Параметры можно распечататьметодв соответствииизинформация。hsdis
инструмент,Он может предоставить дизассемблированный код,Помогает понять скомпилированный код.Обратите внимание, что эти инструменты и методы могут потребовать определенного опыта для понимания и анализа выходных данных. Если вы не знакомы с этими инструментами, возможно, вы захотите ознакомиться с соответствующей документацией или обратиться за профессиональной помощью.
Поскольку эти инструменты и методы могут меняться при обновлении версии JVM, рекомендуется обратиться к официальной документации используемой вами версии JVM для получения последней информации и рекомендаций по использованию.
Object
на Яве,Object
добрый Кусочек Вдобрыйнаследовать Иерархияиз顶конец,Местоиметьсортпо умолчаниюнаследоватьjava.lang.Object
добрый。Object
добрыйпоставлять Понятно Некоторый Проходитьиспользоватьизметод,Этиметоддля Местоиметьвернослонпоставлять Понятнобазовыйиз操делать。к ВниздаObject
добрыйиз Некоторый主хотетьметод:
protected Object clone()
- создаватьивозвращаться该вернослонизодинкопировать。по умолчаниювыполнить БросатьCloneNotSupportedException
。boolean equals(Object obj)
- Указывает, равны ли этому объекту другие объекты. Обычно используется для содержимого объектов Сравнивать.protected void finalize()
- когдасборщик мусор определяется сборщиком объекта, когда выясняется, что ссылок на объект больше не существует. мусоравызовэтотметод。использовать Всуществоватьвернослонодеялопереработкавпередруководитьубирать。Class<?> getClass()
- Возвращает класс времени выполнения этого объекта.int hashCode()
- возвращаться该вернослониз Хэш码ценить。Проходитьчастоиequals()
метод Сотрудничатьиспользовать,Чтобы гарантировать, что равные объекты имеют одинаковый хеш-код.void notify()
- Пробуждает один поток, ожидающий этого объектного монитора.void notifyAll()
- Пробуждает все потоки, ожидающие этого объектного монитора.String toString()
- Возвращает строковое представление этого объекта.void wait()
- привести ккогдавпереднитьждатьобращаться,прямойприезжать Другойодиннитьвызовэтотвернослонизnotify()
илиnotifyAll()
метод。void wait(long timeout)
- привести ккогдавпереднитьждатьобращаться,прямойприезжать Другойодиннитьвызовэтотвернослонизnotify()
илиnotifyAll()
метод,или превышает указанный период ожидания。void wait(long timeout, int nanos)
- привести ккогдавпереднитьждатьобращаться,прямойприезжать Другойодиннитьвызовэтотвернослонизnotify()
илиnotifyAll()
метод,или превышает указанный период ожидания,или ВОЗдогонять过nanos
дополнительныйизнаносекунда。Эти методы предусмотрены по следующим причинам:
Object
вестииспользоватьвызовclone()
)。wait()
иnotify()
метод,Предоставляет механизм межпотокового взаимодействия.toString()
иequals()
метод,Предоставляет настройку по умолчанию для строкового представления объектов.,Разработчикам удобно адаптироваться к конкретным потребностям.hashCode()
метод,Поддерживает хранение и извлечение объектов в хэш-таблицах.finalize()
метод,Хотя не рекомендуется использовать,Но предоставляет объекту возможность выполнять операции по сбору.public class ExampleObject {
public static void main(String[] args) {
Object obj = new Object();
System.out.println("Object hash code: " + obj.hashCode());
System.out.println("Object class: " + obj.getClass().getName());
System.out.println("Object as string: " + obj.toString());
}
}
В этом примере,我ихсоздавать ПонятноодинObject
Пример,ивызов ПонятноhashCode()
、getClass()
иtoString()
метод。
пониматьObject
добрыйпоставлятьиз ЭтиметоддляJava开发ВОЗПриходитьобъяснять Нетчасто Тяжелыйхотеть,Потому что они являются краеугольным камнем языка Java.,А приезжать часто используется при написании и сопровождении кода. С помощью этих методов,Java гарантирует, что объекты разных классов могут выполнять основные операции взаимодействия.
В Java-программировании,Сравниватьдвавернослонданет Взаимнождатьдаодинобщийиз Задача。开发ВОЗ经частоиспользовать==
операториequals()
метод Приходитьруководить Сравнивать,ноэтоихсуществовать Функцияииспользоватьначальствоиметьсутьизокруг Не。В этой статье будет подробно рассмотреноequals()
и==
изокруг Не、соединения и приложения в различных сценариях.
==
оператор:вестииспользоватьиз Сравнивать==
операториспользовать ВСравниватьдвавернослонизвестииспользоватьданеттакой же,То есть указывают ли они на один и тот же объект в памяти.
String s1 = new String("hello");
String s2 = s1;
System.out.println(s1 == s2); // выход правда, потому что s1 и s2 указать на тот же объект
equals()
метод:логика Взаимнождатьиз Сравниватьequals()
методиспользовать ВСравниватьдвавернослонизлогика Взаимнождатьсекс,То есть равны ли значения их свойств. По умолчанию,Object
добрыйизequals()
метод Сравниватьвернослонизвестииспользовать,Но обычно необходимо переписать, чтобы настроить конкретную логику сравнения.
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s3.equals(s4)); // выход правда, потому чтосодержание Взаимнождать
equals()
и==
изокруг Не Сравниватьсодержание:equals()
Сравниватьвернослонизлогика Взаимнождатьсекс,==
Сравниватьвернослонизвестииспользоватьданеттакой же。
equals()
метод Можеткодеялопереписатьквыполнить Инструменттелоиз Сравниватьлогика,и==
операторне могуодеялопереписать。==
Можеткиспользовать ВСравниватьоригинальныйтип данных,иequals()
может толькоиспользовать Ввернослон。equals()
час,Необходимо соблюдать несколько принципов отношений эквивалентности.,нравитьсяс反секс、симметрия、Транзитивность ипоследовательность.equals()
и==
изсоединятьequals()
и==
Всевстречавозвращатьсяtrue
。equals()
метод,Такequals()
на самом деле Сравниватьиздавернослонизвестииспользовать,и==
оператортакой же。equals()
методизлучшие практикиhashCode()
**:нравитьсяфруктыпереписать Понятноequals()
,Следует такжепереписатьhashCode()
,Равные объекты гарантированно будут иметь одинаковый хеш-код.null
**:существовать Сравниватьвпередисследоватьвернослонданетдляnull
。instanceof
**:существоватьруководитьпреобразование типоввперед,использоватьinstanceof
исследоватьвернослониздействительныйдобрыйформа。к Вниздаодинправильныйпереписатьequals()
иhashCode()
из Пример。
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return age == person.age && name.equals(person.name);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
public static void main(String[] args) {
Person p1 = new Person("John", 30);
Person p2 = new Person("John", 30);
System.out.println(p1.equals(p2)); // выход true
}
}
правильныйпониматьииспользоватьequals()
и==
для编写правильныйизвернослон Сравниватьлогикаключевой Тяжелыйхотеть。开发ВОЗотвечать该в соответствии с Сравниватьиз Цельвыбиратьподходящийкогдаизметод,И обеспечить соблюдение соответствующих принципов программирования.
В Java-программировании,Копирование объектов — обычная операция.,尤Чтодакогда需хотетькопироватьодинвернослонкподдерживать статусиз独立сексчас。Копировать точкидляглубокая копияи Мелкая копия,этоихсуществоватьвернослонизкопировать ХОРОШОдляначальствоиметьсутьиздругой。В этой статье будет подробно рассмотрено Разница между глубоким и поверхностным копированием、соединятьа такженравитьсячтона Явевыполнитьэтоих。
Неглубокая копия копирует только сам объект, а не объекты, на которые он ссылается. Если свойства объекта содержат ссылки на другие объекты, поверхностные копии разделяют эти ссылки.
public class ShallowCopyExample {
static class Person {
private String name;
private Address address; // ссылочный тип
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
// Getters and setters
}
static class Address {
private String city;
public Address(String city) {
this.city = city;
}
// Getters and setters
}
public static void main(String[] args) {
Address address = new Address("New York");
Person p1 = new Person("John", address);
Person p2 = new Person("Jane", p1.address); // Неполная копия, ссылка на общий адрес
p2.address.city = "Los Angeles";
System.out.println(p1.address.city); // выход "Los Анджелес", адрес p1иp2 относится к одному и тому же объекту
}
}
Глубокое копирование рекурсивно копирует объект и все объекты, на которые он ссылается, до тех пор, пока все объекты, на которые он ссылается, не будут скопированы. Глубокая копия создает полностью независимую копию объекта.
public class DeepCopyExample {
// Person и Address Определение класса То же, что и выше
static class DeepCopyPerson extends Person {
public DeepCopyPerson(Person original) {
super(original.name); // копироватьбазовый тип
this.address = new Address(original.address.city); // копироватьссылочный тип
}
}
public static void main(String[] args) {
Address address = new Address("New York");
Person p1 = new Person("John", address);
Person p2 = new DeepCopyPerson(p1); // глубокая копия
p2.address.city = "Los Angeles";
System.out.println(p1.address.city); // выход "New York", адреса p1иp2 — это разные объекты
}
}
В Java и глубокое, и поверхностное копирование имеют свои собственные сценарии применения. Выбор того, какой метод копирования использовать, зависит от структуры объекта и потребностей программы. Понимание их различий имеет решающее значение для написания правильных и эффективных программ на Java.