Вложенные классы java для чего нужны
Классы могут быть вложенными (nested), то есть могут быть определены внутри других классов. Частным случаем вложенных классов являются внутренние классы (inner class). Например, имеется класс Person, внутри которого определен класс Account:
public class Program < public static void main(String[] args) < Person tom = new Person("Tom", "qwerty"); tom.displayPerson(); tom.account.displayAccount(); >> class Person < private String name; Account account; Person(String name, String password)< this.name = name; account = new Account(password); >public void displayPerson() < System.out.printf("Person \t Name: %s \t Password: %s \n", name, account.password); >public class Account < private String password; Account(String pass)< this.password = pass; >void displayAccount() < System.out.printf("Account Login: %s \t Password: %s \n", Person.this.name, password); >> >
Внутренний класс ведет себя как обычный класс за тем исключением, что его объекты могут быть созданы только внутри внешнего класса.
Внутренний класс имеет доступ ко всем полям внешнего класса, в том числе закрытым с помощью модификатора private. Аналогично внешний класс имеет доступ ко всем членам внутреннего класса, в том числе к полям и методам с модификатором private.
Ссылку на объект внешнего класса из внутреннего класса можно получить с помощью выражения Внешний_класс.this , например, Person.this .
Объекты внутренних классов могут быть созданы только в том классе, в котором внутренние классы опеределены. В других внешних классах объекты внутреннего класса создать нельзя.
Еще одной особенностью внутренних классов является то, что их можно объявить внутри любого контекста, в том числе внутри метода и даже в цикле:
public class Program < public static void main(String[] args) < Person tom = new Person("Tom"); tom.setAccount("qwerty"); >> class Person < private String name; Person(String name)< this.name = name; >public void setAccount (String password) < class Account< void display()< System.out.printf("Account Login: %s \t Password: %s \n", name, password); >> Account account = new Account(); account.display(); > >
Статические вложенные классы
Кроме внутренних классов также могут быть статические вложенные классы. Статические вложенные классы позволяют скрыть некоторую комплексную информацию внутри внешнего класса:
class Math < public static class Factorial< private int result; private int key; public Factorial(int number, int x)< result=number; key = x; >public int getResult() < return result; >public int getKey() < return key; >> public static Factorial getFactorial(int x) < int result=1; for (int i = 1; i return new Factorial(result, x); > >
Здесь определен вложенный класс для хранения данных о вычислении факториала. Основные действия выполняет метод getFactorial , который возвращает объект вложенного класса. И теперь используем классы в методе main:
public static void main(String[] args)
Difference Between & and && in Java
In this section, we will discuss the two most important operators & and && in Java and also see the key differences between logical and bitwise operators along with its uses.

& Operator
The single AND operator (&) is known as the Bitwise AND operator. It operates on a single bit. It takes two operands. A bit in the result is 1 if and only if both of the corresponding bits in the operands are 1. The result of the operator may be any number. For example:
&& Operator
The double AND operators (&&) are known as logical AND operators. It is usually used in loops and conditional statements. It is usually used in Boolean expressions. The result of && is always 0 or 1.
Difference Between & and &&
The key difference between && and & operators is that && supports short-circuit evaluations while & operator does not.
Another difference is that && will evaluate the expression exp1, and immediately return a false value if exp1 is false. While & operator always evaluates both expressions (exp1 and exp2) before retiring an answer.
| S.N. | Basis | & Operator | && Operator |
|---|---|---|---|
| 1 | Operator | It is a bitwise AND operator. | It is a logical AND operator. |
| 2 | Evaluation | It evaluates both the left and right side of the given expression. | It only evaluates the left sides of the given expression. |
| 3 | Operates on | It operates on Boolean data types as well as on bits. | It operates only on Boolean datatype. |
| 4 | Uses | Used to check logical condition and also used to mask off certain bits such as parity bits. | Used only to check the logical conditions. |
| 5 | Example | z = x & y | if (y > 1 && y > x) |
Let’s understand bitwise and logical and operator through a Java program.
LogicalAndExample.java
Output:
true false
BitwiseAndExample.java
Внутренние и вложенные Java классы
В Java вложенные классы – это классы, которые определены внутри другого класса.
Цель – четко сгруппировать вложенный класс с окружающим его классом, сигнализируя о том, что эти два класса должны использоваться вместе. Или, возможно, что вложенный должен использоваться только внутри его вмещающего (владеющего) класса.
Java-разработчики часто используют внутренние классы (нестатические вложенные) – это только один из нескольких различных типов:
- статические;
- нестатические;
- локальные;
- анонимные.
Вложенные считаются членами включающего их класса. Таким образом, могут быть объявлены как открытые, пакетные (без модификатора доступа), защищенные и приватные. Поэтому могут наследоваться подклассами.
Статические
public class Outer < public static class Nested < >>
Чтобы создать экземпляр класса Nested, вы должны сослаться на него, добавив к нему префикс имени внешнего класса, например:
Outer.Nested instance = new Outer.Nested();
Статический тип – это, по сути, обычный класс, который только что был вложен в другой класс. Может обращаться к переменным экземпляра включающего класса только через ссылку на его экземпляр.
Нестатические внутренние классы
Нестатические вложенные также называются внутренними и связаны с экземпляром включающего класса. Таким образом, вы должны сначала создать экземпляр окружающего класса, чтобы создать экземпляр внутреннего:
public class Outer < public class Inner < >>
Вот как вы создаете экземпляр класса Inner:
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner();
Обратите внимание, как вы ставите new после ссылки на внешний класс, чтобы создать экземпляр внутреннего.
Нестатические классы (внутренние классы) имеют доступ к полям включающего класса, даже если они объявлены закрытыми:
public class Outer < private String text = "I am private!"; public class Inner < public void printText() < System.out.println(text); >> >
Обратите внимание, как метод printText() класса Inner ссылается на поле частного текста класса Outer. Это вполне возможно. Вот как вы бы вызвали метод printText():
Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.printText();
Shadowing
Если внутренний класс объявляет поля или методы с теми же именами, что и у поля или методов в своем включающем классе, внутренние поля или методы называются внешними полями или методами :
public class Outer < private String text = "I am Outer private!"; public class Inner < private String text = "I am Inner private"; public void printText() < System.out.println(text); >> >
В приведенном выше примере класс Outer и Inner содержит поле с именем text. Когда класс Inner ссылается на текст, он ссылается на свое собственное поле. Когда Outer ссылается на текст, он также ссылается на свое собственное поле.
Java позволяет классу Inner ссылаться на текстовое поле класса Outer. Для этого ему нужно добавить префикс ссылки на текстовое поле к Outer.this. (имя внешнего класса + .this. + имя поля), например:
public class Outer < private String text = "I am Outer private!"; public class Inner < private String text = "I am Inner private"; public void printText() < System.out.println(text); System.out.println(Outer.this.text); >> >
Теперь метод Inner.printText() будет печатать поля Inner.text и Outer.text.
Локальные
Локальные классы в Java похожи на внутренние (нестатические вложенные), которые определены внутри метода или блока контекста() внутри метода:
class Outer < public void printText() < class Local < >Local local = new Local(); > >
Характеристика локальных классов:
- Доступ возможен только из метода или блока контекста, в котором они определены.
- Могут получать доступ к членам (полям и методам) своего окружающего класса, как и обычные внутренние.
- Могут обращаться к локальным переменным внутри того же метода или блока области действия, если эти переменные объявлены как окончательные.
- Из Java 8 могут обращаться к локальным переменным и параметрам метода, в котором объявлен локальный класс. Параметр должен быть объявлен как final или быть им. Фактически это означает, что переменная никогда не изменяется после инициализации. Параметры метода часто являются фактически окончательными.
- Могут быть объявлены внутри статических методов. В этом случае локальный класс имеет доступ только к статическим частям окружающего класса.
- Не могут содержать все виды статических объявлений (допустимы константы – переменные объявлены как static final), потому что не являются статичными по своей природе – даже если они объявлены внутри статического метода.
- Для них применяются те же правила затенения, что и для внутренних классов.
Анонимные
Анонимные классы – это вложенные без имени класса. Они обычно объявляются либо как подклассы существующего класса, либо как реализации некоторого интерфейса.
Определяются, когда они создаются. Вот пример, который объявляет анонимный подкласс суперкласса с именем SuperClass:
public class SuperClass < public void doIt() < System.out.println("SuperClass doIt()"); >>
SuperClass instance = new SuperClass() < public void doIt() < System.out.println("Anonymous class doIt()"); >>; instance.doIt();
Запуск этого кода приведет к тому, что анонимный класс doIt() будет напечатан в System.out. Он расширяет SuperClass и переопределяет метод doIt().
Анонимный класс также может реализовывать интерфейс вместо расширения класса:
public interface MyInterface
MyInterface instance = new MyInterface() < public void doIt() < System.out.println("Anonymous class doIt()"); >>; instance.doIt();
Как вы можете видеть, анонимные классы, реализующий интерфейс и расширяющий другой класс очень похожи.
Этот тип класса может получить доступ к членам включающего класса. Также к локальным переменным, которые объявлены как final.
Вы можете объявить поля и методы внутри такого класса, но не можете объявить конструктор. Вместо этого возможно объявить статический инициализатор:
final Strint textToPrint = "Text. "; MyInterface instance = new MyInterface() < private String text; //static initializer < this.text = textToPrint; >public void doIt() < System.out.println(this.text); >>; instance.doIt();
К этому типу класса применяются те же правила дублирования, что и к внутренним.
Преимущества
Преимущества в том, что вы можете группировать классы, которые принадлежат друг другу. Возможно сделать это, поместив их в один и тот же пакет, но размещение одного класса внутри другого делает еще более сильную группировку.
Иногда они видны только включающему классу, используется только внутри и, следовательно, никогда не видны вне охватывающего класса. В других случаях вложенный виден за пределами его окружающего класса, но может использоваться только вместе с включающим.
Примером может быть класс Cache. Внутри Cache вы можете объявить класс CacheEntry, который может содержать информацию о конкретной записи в кэше (кэшированное значение, время вставки, количество обращений и т. д.).
Пользователи Cache могут никогда не увидеть CacheEntry, если им не нужно получать информацию о самом CacheEntry, а только кэшированное значение. Тем не менее, Cache может сделать CacheEntry видимым для внешнего мира, чтобы они могли получить доступ не только к кэшированному значению (например, к информации о том, когда значение было обновлено в последний раз и т. д.).
Вот два скелета реализации Cache, иллюстрирующие эти моменты:
public class Cache < private Map cacheMap = new HashMap(); private class CacheEntry < public long timeInserted = 0; public object value = null; >public void store(String key, Object value) < CacheEntry entry = new CacheEntry(); entry.value = value; entry.timeInserted = System.currentTimeMillis(); this.cacheMap.put(key, entry); >public Object get(String key) < CacheEntry entry = this.cacheMap.get(key); if(entry == null) return null; return entry.value; >>
public class Cache < private Map cacheMap = new HashMap(); public class CacheEntry < public long timeInserted = 0; public object value = null; >public void store(String key, Object value) < CacheEntry entry = new CacheEntry(); entry.value = value; entry.timeInserted = System.currentTimeMillis(); this.cacheMap.put(key, entry); >public Object get(String key) < CacheEntry entry = this.cacheMap.get(key); if(entry == null) return null; return entry.value; >public CacheEntry getCacheEntry(String key) < return this.cacheMap.get(key); >>
Первый класс Cache скрывает свой вложенный класс CacheEntry, в то время как второй класс Cache предоставляет его.
Logical AND (&&)
The logical AND ( && ) (logical conjunction) operator for a set of boolean operands will be true if and only if all the operands are true . Otherwise it will be false .
More generally, the operator returns the value of the first falsy operand encountered when evaluating from left to right, or the value of the last operand if they are all truthy.
Try it
Syntax
Description
If a value can be converted to true , the value is so-called truthy. If a value can be converted to false , the value is so-called falsy.
Examples of expressions that can be converted to false are:
- false ;
- null ;
- NaN ;
- 0 ;
- empty string ( «» or » or « );
- undefined .
The AND operator preserves non-Boolean values and returns them as they are:
= "" && "foo"; // result is assigned "" (empty string) result = 2 && 0; // result is assigned 0 result = "foo" && 4; // result is assigned 4
Even though the && operator can be used with non-Boolean operands, it is still considered a boolean operator since its return value can always be converted to a boolean primitive. To explicitly convert its return value (or any expression in general) to the corresponding boolean value, use a double NOT operator or the Boolean constructor.
Short-circuit evaluation
The logical AND expression is a short-circuit operator. As each operand is converted to a boolean, if the result of one conversion is found to be false , the AND operator stops and returns the original value of that falsy operand; it does not evaluate any of the remaining operands.
Consider the pseudocode below.
(some falsy expression) && expr
The expr part is never evaluated because the first operand (some falsy expression) is evaluated as falsy. If expr is a function, the function is never called. See the example below:
function A() console.log("called A"); return false; > function B() console.log("called B"); return true; > console.log(A() && B()); // Logs "called A" to the console due to the call for function A, // && evaluates to false (function A returns false), then false is logged to the console; // the AND operator short-circuits here and ignores function B
Operator precedence
The AND operator has a higher precedence than the OR operator, meaning the && operator is executed before the || operator (see operator precedence).
true || false && false; // true true && (false || false); // false (2 === 3) || (4 0) && (1 === 1); // false
Examples
Using AND
The following code shows examples of the && (logical AND) operator.
= true && true; // t && t returns true a2 = true && false; // t && f returns false a3 = false && true; // f && t returns false a4 = false && 3 === 4; // f && f returns false a5 = "Cat" && "Dog"; // t && t returns "Dog" a6 = false && "Cat"; // f && t returns false a7 = "Cat" && false; // t && f returns false a8 = "" && false; // f && f returns "" a9 = false && ""; // f && f returns false
Conversion rules for booleans
Converting AND to OR
The following operation involving booleans:
&& bCondition2
is always equal to:
!(!bCondition1 || !bCondition2)
Converting OR to AND
The following operation involving booleans:
|| bCondition2
is always equal to:
!(!bCondition1 && !bCondition2)
Removing nested parentheses
As logical expressions are evaluated left to right, it is always possible to remove parentheses from a complex expression provided that certain rules are followed.
The following composite operation involving booleans:
|| (bCondition2 && bCondition3)
is always equal to:
|| bCondition2 && bCondition3
Specifications
| Specification |
|---|
| ECMAScript Language Specification # prod-LogicalANDExpression |
Browser compatibility
BCD tables only load in the browser