Побитовое «и» любого байтового значения и 0xff всегда будут возвращать исходное значение.
Это просто, если вы нарисуете биты на диаграмме:
00101010 42
11111111 and 0xff
--------
00101010 gives 42
Под «анонимным классом», я полагаю, вы имеете в виду анонимный внутренний класс .
Анонимный внутренний класс может пригодиться при создании экземпляра объекта с определенным " extras ", например методы перегрузки, без фактического подкласса класса.
Я использую его как ярлык для присоединения слушателя событий:
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// do something
}
});
Используя этот метод, кодирование немного быстрее, так как мне не нужно создавать дополнительный класс, который реализует ActionListener
- я могу просто создать анонимный внутренний класс, не создавая отдельный класс.
Я использую это техника для «быстрых и грязных» задач, когда создание целого класса кажется ненужным. Наличие нескольких анонимных внутренних классов, которые выполняют точно то же самое, должны быть реорганизованы в фактический класс, будь то внутренний класс или отдельный класс.
Анонимные внутренние классы фактически закрывают, поэтому их можно использовать для эмуляции лямбда-выражений или «делегатов». Например, возьмите этот интерфейс:
public interface F<A, B> {
B f(A a);
}
Вы можете использовать это анонимно, чтобы создать функцию первого класса в Java. Допустим, у вас есть следующий метод, который возвращает первое число, большее, чем i в данном списке, или i, если число не больше:
public static int larger(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n > i)
return n;
return i;
}
И у вас есть другой метод, который возвращает первый номер меньшего размера чем i в данном списке, или i, если число меньше:
public static int smaller(final List<Integer> ns, final int i) {
for (Integer n : ns)
if (n < i)
return n;
return i;
}
Эти методы почти идентичны. Используя первоклассный тип функции F, мы можем переписать их в один метод следующим образом:
public static <T> T firstMatch(final List<T> ts, final F<T, Boolean> f, T z) {
for (T t : ts)
if (f.f(t))
return t;
return z;
}
Вы можете использовать анонимный класс для использования метода firstMatch:
F<Integer, Boolean> greaterThanTen = new F<Integer, Boolean> {
Boolean f(final Integer n) {
return n > 10;
}
};
int moreThanMyFingersCanCount = firstMatch(xs, greaterThanTen, x);
Это действительно надуманный пример, но его легко увидеть, что возможность передавать функции вокруг, как если бы они были значениями, является довольно полезной функцией. См. «Может ли ваш язык программирования делать это» самим Джоэлем.
Хорошая библиотека для программирования Java в этом стиле: Функциональная Java.
Еще одно преимущество: поскольку вы знаете, что Java не поддерживает множественное наследование, поэтому, если вы используете класс типа «Thread» как анонимный класс, тогда класс по-прежнему имеет одно пространство, оставшееся для расширения любого другого класса.
Анонимный внутренний класс используется для создания объекта, который никогда не будет ссылаться снова. Он не имеет имени и объявляется и создается в том же самом заявлении. Это используется там, где вы обычно используете переменную объекта. Вы заменяете переменную ключевым словом new
, вызовом конструктора и определением класса внутри {
и }
.
При написании Threaded Program в Java это обычно выглядит так:
ThreadClass task = new ThreadClass();
Thread runner = new Thread(task);
runner.start();
Используемый здесь ThreadClass
будет определяться пользователем. Этот класс будет реализовывать интерфейс Runnable
, необходимый для создания потоков. В ThreadClass
также необходимо реализовать метод run()
(только метод из Runnable
). Понятно, что избавление от ThreadClass
было бы более эффективным, и именно поэтому существуют Анонимные Внутренние Классы.
Посмотрите на следующий код
Thread runner = new Thread(new Runnable() {
public void run() {
//Thread does it's work here
}
});
runner.start();
Этот код заменяет ссылку сделанный в task
в самом верхнем примере. Вместо того, чтобы иметь отдельный класс, Анонимный Внутренний Класс внутри конструктора Thread()
возвращает неназванный объект, который реализует интерфейс Runnable
и переопределяет метод run()
. Метод run()
будет включать в себя заявления внутри, которые выполняют работу, требуемую потоком.
Отвечая на вопрос о том, является ли анонимные внутренние классы одним из преимуществ Java, я должен сказать, что я не совсем уверен, поскольку я не знаком со многими языками программирования на данный момент. Но я могу сказать, что это, безусловно, более быстрый и простой способ кодирования.
Ссылки: Sams Teach Yourself Java в 21 день Седьмое издание
Одно из основных применений анонимных классов в завершении класса, которое называется guardizer . В Java-мире использование методов finalize следует избегать, пока вы им не понадобятся. Вы должны помнить, что когда вы переопределяете метод finalize для подклассов, вы всегда должны вызывать super.finalize()
, потому что метод finalize суперкласса не будет вызываться автоматически, и у вас могут возникнуть проблемы с утечками памяти.
, поэтому, учитывая упомянутый выше факт, вы можете просто использовать анонимные классы, например:
public class HeavyClass{
private final Object finalizerGuardian = new Object() {
@Override
protected void finalize() throws Throwable{
//Finalize outer HeavyClass object
}
};
}
Используя эту технику, вы освободили себя и своих других разработчиков от вызова super.finalize()
для каждого подкласса из HeavyClass
, который нуждается в методе окончательной доработки.
Внутренний класс связан с экземпляром внешнего класса и есть два специальных вида: Локальный класс и Анонимный класс . Анонимный класс позволяет нам объявлять и создавать экземпляр класса одновременно, поэтому делает код кратким. Мы используем их, когда нам нужен локальный класс только один раз, поскольку у них нет имени.
Рассмотрим пример из doc , где мы имеем класс Person
:
public class Person {
public enum Sex {
MALE, FEMALE
}
String name;
LocalDate birthday;
Sex gender;
String emailAddress;
public int getAge() {
// ...
}
public void printPerson() {
// ...
}
}
, и у нас есть способ печати элементов, которые соответствуют критериям поиска:
public static void printPersons(
List<Person> roster, CheckPerson tester) {
for (Person p : roster) {
if (tester.test(p)) {
p.printPerson();
}
}
}
, где CheckPerson
- это интерфейс, такой как:
interface CheckPerson {
boolean test(Person p);
}
Теперь мы можем использовать анонимный класс, который реализует этот интерфейс, чтобы указать критерии поиска как:
printPersons(
roster,
new CheckPerson() {
public boolean test(Person p) {
return p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25;
}
}
);
. Здесь интерфейс очень прост, и синтаксис анонимного класса кажется громоздким и непонятным.
В Java 8 введен термин функциональный интерфейс , который является интерфейсом только с одним абстрактным методом, поэтому можно сказать, CheckPerson
является функциональным интерфейсом. Мы можем использовать выражение Lambda Expression , которое позволяет нам передать функцию как аргумент метода как:
printPersons(
roster,
(Person p) -> p.getGender() == Person.Sex.MALE
&& p.getAge() >= 18
&& p.getAge() <= 25
);
Вместо стандартного функционального интерфейса Predicate
мы можем использовать интерфейс CheckPerson
, что дополнительно уменьшит требуемый код.
GuideLines для анонимного класса.
например:
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
});
ref.getClass().newInstance()
.
– icza
11 July 2014 в 12:54
Да, анонимные внутренние классы определенно являются одним из преимуществ Java.
С анонимным внутренним классом у вас есть доступ к конечным и переменным-членам окружающего класса, и это очень удобно в слушателях и т. д. .
Но главное преимущество заключается в том, что внутренний код класса, который (по крайней мере должен быть) тесно связан с окружающим классом / методом / блоком, имеет конкретный контекст (окружающий класс, метод и блок). [/ д2]
Они обычно используются в качестве подробной формы обратного вызова.
Я полагаю, вы могли бы сказать, что они являются преимуществом по сравнению с отсутствием их, и каждый раз нужно создавать именованный класс, но аналогичные концепции реализованы гораздо лучше на других языках (как закрытие или блоки)
Вот пример качания
myButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
// do stuff here...
}
});
. Хотя это все еще бесполезно многословно, это намного лучше, чем заставлять вас определять названный класс для каждого раздающего прослушивателя, подобного этому (хотя в зависимости от ситуации и повторного использования это может быть лучшим подходом)
myButton.addActionListener(e -> { /* do stuff here */})
или myButton.addActionListener(stuff)
будет терпеливым.
– Samuel Edwin Ward
20 May 2015 в 22:42
new Thread() {
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
System.out.println("Exception message: " + e.getMessage());
System.out.println("Exception cause: " + e.getCause());
}
}
}.start();
Это также один из примеров анонимного внутреннего типа с использованием thread
Анонимный внутренний класс используется в следующем сценарии:
1.) Для переопределения (подкласс), когда определение класса не используется, кроме текущего случая:
class A{
public void methodA() {
System.out.println("methodA");
}
}
class B{
A a = new A() {
public void methodA() {
System.out.println("anonymous methodA");
}
};
}
2 .) Для реализации интерфейса, когда реализация интерфейса требуется только для текущего случая:
interface interfaceA{
public void methodA();
}
class B{
interfaceA a = new interfaceA() {
public void methodA() {
System.out.println("anonymous methodA implementer");
}
};
}
3.) Аргумент Определенный Анонимный внутренний класс:
interface Foo {
void methodFoo();
}
class B{
void do(Foo f) { }
}
class A{
void methodA() {
B b = new B();
b.do(new Foo() {
public void methodFoo() {
System.out.println("methodFoo");
}
});
}
}
Лучший способ оптимизации кода. Кроме того, мы можем использовать для переопределения метод класса или интерфейса.
import java.util.Scanner;
abstract class AnonymousInner {
abstract void sum();
}
class AnonymousInnerMain {
public static void main(String []k){
Scanner sn = new Scanner(System.in);
System.out.println("Enter two vlaues");
int a= Integer.parseInt(sn.nextLine());
int b= Integer.parseInt(sn.nextLine());
AnonymousInner ac = new AnonymousInner(){
void sum(){
int c= a+b;
System.out.println("Sum of two number is: "+c);
}
};
ac.sum();
}
}
Вы можете использовать анонимный класс
TreeSet treeSetObj = new TreeSet(new Comparator()
{
public int compare(String i1,String i2)
{
return i2.compareTo(i1);
}
});
Вы используете его в ситуациях, когда вам нужно создать класс для определенной цели внутри другой функции, например, в качестве слушателя, как runnable (для создания потока) и т. д.
Идея что вы вызываете их изнутри кода функции, чтобы вы никогда не ссылались на них в другом месте, поэтому вам не нужно их называть. Компилятор просто перечисляет их.
Они по сути являются синтаксическим сахаром и обычно должны перемещаться в другом месте по мере их роста.
Я не уверен, является ли это одним из преимуществ Java, хотя, если вы их используете (и мы все часто используем их, к сожалению), то вы можете утверждать, что они одни.
Анонимный внутренний класс может быть полезным, предоставляя различные реализации для разных объектов. Но он должен использоваться очень экономно, поскольку он создает проблему для удобочитаемости программы.
Я иногда использую их в качестве синтаксического взлома для создания карты:
Map map = new HashMap() {{
put("key", "value");
}};
vs
Map map = new HashMap();
map.put("key", "value");
Он сохраняет некоторую избыточность при выполнении множества операторов put. Тем не менее, у меня также возникают проблемы с этим, когда внешний класс должен быть сериализован посредством удаленного доступа.
Кажется, здесь никто не упоминается, но вы также можете использовать анонимный класс для хранения аргумента generic type (который обычно теряется из-за стирания типа) :
public abstract class TypeHolder<T> {
private final Type type;
public TypeReference() {
// you may do do additional sanity checks here
final Type superClass = getClass().getGenericSuperclass();
this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
public final Type getType() {
return this.type;
}
}
Если вы экземпляр этого класса анонимным способом
TypeHolder<List<String>, Map<Ineger, Long>> holder =
new TypeHolder<List<String>, Map<Ineger, Long>>() {};
, тогда такой экземпляр holder
будет содержать неидентифицированное определение пройденного типа.
Это очень удобно для создания валидаторов / десериализаторов. Кроме того, вы можете создавать типичный тип с отражением (так что если вы когда-либо хотели сделать new T()
в параметризованном типе - приветствуется!) [/ G1].
overloading methods
, а неoverriding methods
? – Tarun 14 September 2016 в 12:48