Professional Documents
Culture Documents
Java For Print
Java For Print
Hi,
Please let me know if you have compilation errors or runtime errors that you think is related to this
library.
‘commons-collections’ - https://commons.apache.org/proper/commons-collections/
It added many powerful data structures that accelerate development of most significant Java
applications. Since that time it has become the recognised standard for collection handling in Java.
Commons-Collections seek to build upon the JDK classes by providing new interfaces, implementations
and utilities. There are many features, including:
• Bag interface for collections that have a number of copies of each object
• BidiMap interface for maps that can be looked up from value to key as well and key to value
• MapIterator interface to provide simple and quick iteration over maps
• Transforming decorators that alter each object as it is added to the collection
• Composite collections that make multiple collections look like one
• Ordered maps and sets that retain the order elements are added in, including an LRU based map
• Reference map that allows keys and/or values to be garbage collected under close control
• Many comparator implementations
• Many iterator implementations
• Adapter classes from array and enumerations to collections
• Utilities to test or create typical set-theory properties of collections such as union, intersection,
and closure
=================================================
System Properties
The Classpath
Това е env variable, която предоставя на приложението списък от места където може да се търси
даден ресурс. Най-добрия пример е път към executable програми. Примерно ако искам да
стартирам от моята java програма, някакъв файл, който е на python или на bash script.
Java CLASSPATH environment variable е списък от локации, където се търси за Java class файлове.
JVM-a и компилатора използват CLASSPATH-a, когато търсят пакети и класове. Пример е
директория за jar файлове. (също и zip, jar и zip реално са същия формат). Jar файловете са по-
специализирани, тъй като включват допълнителни metadata файлове, които описват
съдържанието на jar-a. Те се създават от JDK jar utility.
Java - Unicode поддръжка. Това означава, че ще са необходими поне два байта (bytes), да
пресъздадат всеки символ вътрешно.
Unicode (стандарт за енкодване и представяне на текстови символи, дефинира над 100 хил.
символа). Енкодване на символи (character encoding) означава използване на някаква определена
енкодинг система, която позволява да се назначи номер на всеки от символите за дигитално
представяне.
Реално ако въвеждам всичко като стринг, аз рискувам символите да трябва да се енкодват и
декодват постоянно.
Тука пише, че реално java кода, може да се пише във всякакъв вид езици, примерно имена на
променливи, класове и т.н.
The Java char type and String class съпортват Unicode values. Вътрешно текста е сторнат, като
multibyte characters using the UTF-16 encoding.
Unicode is also very ASCII-friendly (ASCII is the most common character encoding for English).
The first 256 characters are defined to be identical to the first 256 characters in the ISO 8859-1 (Latin-1)
character set, so Unicode is effectively backward-compatible with the most common English character
sets.
Furthermore, one of the most common file encodings for Unicode, called UTF-8, preserves ASCII values
in their single byte form.
This encoding is used by default in compiled Java class files, so storage remains compact for English text.
\uxxxx
xxxx is a sequence of one to four hexadecimal digits. The escape sequence indicates an ASCII-encoded
Unicode character.
This is also the form Java uses to output (print) Unicode characters in an environment that doesn’t
otherwise support them.
Java also comes with classes to read and write Unicode character streams in specific encodings,
including UTF-8.
Types
Типовата система на всеки от програмните езици описва как data елементите (променливи и
константи), се асоциират с конкретни места в паметта и как се отнасят едно към друго.
- Референтни типове (class types): обекти и масиви, казват се референтни типове, защото
реферират към по-голям тип данни (large data type), който се предава by reference. Generic
типовете са вид разновидност на този тип.
Variable declaration and initialization
Важно:
Локалните променливи,(които търпят докато се изпълни метода и т.н.), трябва задължително да
се инициализират.
Променливите, които са част от класа, може и да не се инициализират. Той класа ги сетва към
дефолтни стойносити: char = null, numеric types = 0, boolean = false.
Reference Types
Най-важното нещо е принципа, че класовете в java винаги имат parent/child relationship и child
класа, наследява всички методи и пропъртита на parent-а.
Това означава, че той съдържа в себе си parent класа и променливи, които изискват parent класа
или методи, които изискват такъв параметър, спокойно могат да бъдат инициализирани с обект на
child класа.
Това е т.н. subtype полиморфизъм и е една от типичните черти на обектно ориентираните езици.
Примитивните типове във Java се използват и пренасят "by value", т.е. копират се един в друг,
докато reference types, винаги се достъпват по референция.
!!!! Значи променливата, която очаква определен тип обект/клас, държи поинтер към обектите от
този тип или субтип, и вече при инициализация ние просто даваме името на дадения обект и така
се получава пълна референция, т.е. референцията само държи поинтер към дадения обект, а не
самия обект.
====================
Expression-a произвежда резултат (value), което ще се използва в друг експешън или стейтмънт.
A continue statement causes for and while loops to move on to their next iteration by returning to the
point where they check their condition.
A break causes Java to stop the current block statement and resume execution after it. In the following
example, the while loop goes on endlessly until the condition() method returns true, triggering a break
statement that stops the loop and proceeds at the point marked “after while.”
labelOne:
while ( condition ) {
...
labelTwo:
while ( condition ) {
...
Exceptions
----------
Много пакети дефинират техен собствен тип ексепшъни, които обикновенно са подкласове на
Exception или са част от важния подклас RuntimeException.
In Java 7, there is an alternative to using multiple catch clauses, and that is to handle multiple discrete
exception types in a single catch clause using the “|” or syntax:
try {
// read from network...
// write to file..
catch ( ZipException | SSLException e ) {
logException( e );
}
Assertions
----------
Нещо като допълнително тестване на дадено условие, след което показва съобщение на
потребителя. Дали евентуално не може да се използва в транзакции свързни с инсърт на нещо в
база или нещо от сорта.
Нещо като try/catch, или по-скоро рънтайм тестване на някакво условие.
Използва се специална дума assert.
Като си има и механизъм за изпращане на съобщения до user-ите.
assert foo != null : "foo is null!" // shows message "foo is null!" to user
Array Types:
int [] arrayOfInts;
Пример за синтаксиса:
Можем да имаме и много мерен масив, като той трябва да е от един и същи тип, не може
различни.
===========================
== Chapter 5. Objects in Java ==
===========================
- Hide as much of your implementation as possible. Never expose more of the internals of an
object than you need to.
This is key to building maintainable, reusable code.
Avoid public variables in your objects, with the possible exception of constants.
Instead define accessor methods to set and return values (even if they are simple types).
Later, when you need to, you’ll be able to modify and extend the behavior of your
objects without breaking other classes that rely on them.
- Създавай специализирани обекти, само когато има нужда от това. Наместо това е по-
добре да се използват композитни обекти. Композиране на обекти наместо наследяване
на обекти. Композиране означава, като използваме обект в друг обект. Наследяването
чупи енкапсулацията на обекта и трябва да се използва само когато има нужда от това.
Тоест ние няма да наследяваме целия интерфейс на обекта (и неговия тип), може просто
да делегираме определена работа на новия обект, чрез композиране.
Допълнително да се потърси каква е разликата между composition и inheritance.
Only expose classes that you intend other people to use. The more loosely coupled your objects
are, the easier it will be to reuse them later.
Classes
-------
Pendulum p;
p = new Pendulum();
В първия ред, ние не създаваме обект Pendelium, а само декларираме променлива, която държи
референция към обект от тип Pendelium.
Трябва да създадем обекта с new, както се вижда на втория ред.
Методите на обекта (инстанционните, не статичните) достъпват пропъртитата на обекта, но java
обекта, няма свое копие на самите методи, което да се копира при всяка инстанция.
Several factors affect whether class members can be accessed from another class. You can use the
visibility modifiers public, private, and protected to control access;
Classes can also be placed into a package, which affects their scope.
The private modifier, for example, designates a variable or method for use only by other members of
the class itself.
Static Members
--------------
Достъпват се както през инстанцията на обекта (стойността им е еднаква за всички инстанции),
така и директно през класа.
Име на класа . име на статик променливата.
Много са полезни за данни, които се шерват между различните класове, по време на рънтайм.
Static + final думичката се използват за създаване на константи.
Статик членовете са полезни за флагове и идентификатори, които могат да бъдат достъпни
отвсякъде. Както и за стойности, които са нужни на конструкторите на класовете да създадат
инстанция на даден клас.
Enumeration
-----------
An enum is a special "class" that represents a group of constants (unchangeable variables, like final
variables).
To create an enum, use the enum keyword (instead of class or interface), and separate the constants
with a comma. Note that they should be in uppercase letters:
enum Level {
LOW,
MEDIUM,
HIGH
}
Methods:
--------
If the method is executing concurrently in different threads, each thread has its own version of the
method’s local variables.
Принципно локалните променливи се унищожават, след като метода спре да се изпълнява, обаче
има една специфика, ако имаме локален обект.
If, however, we assign the object to an instance variable of an object, pass it as an argument to another
method, or pass it back as a return value, it may be saved by another variable holding its reference.
We’ll discuss object creation and garbage collection in more detail shortly.
void myMethod() {
int foo = 42;
int bar;
bar = 99;
bar += 1; // would be OK here
}
boolean - java.lang.Boolean
char - java.lang.Character
При този пример ефекта е един и същ. Стринга във втория случай се парсва, като ако има грешка
при
парсването се хвърля ексепшън.
Не е кой знае какво. Просто трябва да знаем, че понякога Java автоматично wrap-ва и unwraps-ва.
Най-типичния пример е използването на метода printf(), който принти всички аргументи, които му
се предадат.
Такъв тип методи (които приемат различен брой аргументи) е еквивалентен на методите, които
приемат масив от даден тип обекти.
Разликата е, че компилатора автоматично прави така, че метода да приема индивидуални comma
separated values, след което ги пакетира
в масив. Синатаксиса за деклариране на такъв тип методи е ( ... )
Пример:
void printObjects( Object ... list ) {
// list is an Object []
for( Object o : list )
System.out.println( o );
}
Може да имаме първоначално някколко бройки фиксирани аргументи, след което да имаме
varargs декларация.
Method Overloading
------------------
Това е възможността да дефинираме различни методи с едно и също име в един клас и когато
метода е извикан компилатора избира коректния метод за изпълнение на база на аргументите,
които са му предадени. Различен тип или брой аргументи.
Идеята е да се създадат методи, които се държат по еднакъв начин при различен тип аргументи.
Object Creation
---------------
Обектите в Java са алокирани в системната heap memory space. За разлика от някои други
програмни езици, Java програмистите нямат възможност да управляват тази памет. Java го прави
автоматично.
Constructors
------------
Метод, който се извиква при създаване на обекта и дава възможност да се сетъпнат някакви
стойности в обекта.
Могат да приемат аргументи и да бъдат overloaded, както и останалите методи, но не се
наследяват като останалите методи.
Ако имаме няколко конструктора т.н. дефолтен конструктор, ще бъде този, който е без никакви
аргументи.
Ако сетнем референция към обект на null > това е ясен знак за garbage collection.
Конструкторите могат да бъдат дефинирани като public, private или protected, за да се контролира
тяхната видимост, но не могат да се дефинират като abstract, synchronized(!!!! да прочета
допълнително за това), or final.
Car( String m ) {
int doors = determineDoors();
this( m, doors ); // Error: constructor call
// must be first statement
}
class Car {
...
final int default_doors = 4;
...
Car( String m ) {
this( m, default_doors ); // Error: referencing
// uninitialized variable
}
...
}
Тук във втория пример, също ще даде грешка, защотото променливата не е инициализирана, но
това може да се преодолее, ако използваме static променливи.
Instance initializer blocks могат да бъдат нещо като допълнение към instance variable initialization-a.
Викат се когато се инициализират променливите.
Пример:
class MyClass {
Properties myProps = new Properties();
// set up myProps
{
myProps.put("foo", "bar");
myProps.put("boo", "gee");
}
int a = 5;
Object Destruction
------------------
Наличието на garbage collector, който да разрушава обектите, помага на програмистите, тъй като
не се налага да търсим постоянно memory leak-ове, както например C, C++ програмистите.
Когато всички референции към обекта са заминали и той не е достъпен повече, garbage collector-а
го маркира като unreachable и изисква обратно паметта, към пула с налична памет, за работа на
програмата.
Има различни алгоритми. Първоначалните алгоритми не са хващали обекти, които реферират
един към друг.
Те са част от runtime system-a на Java.
Преди даден обект да се разруши се вика неговия finalize() метод, който може да зачисти разни
неща. Връзки към бази и т.н.
Но идеята, е че не се знае кога това ще се случи. Ако има достатъчно място на машината garbage
collector-а може никога да не се извика.
Enumerations
------------
// usage
setDay( Weekday.Sunday );
По-горния пример според мен казва, че директно стойността на член на енум класа, става видима
и може да се използва за
параметър на метод.
Enum Values
-----------
Списъка със всички enum values, можем да вземем със static values() method.
Имаме билднат compareTo() метод в енум типовете, който сравнява една стойност със друга, но
трябва да са от същия енум тип.
enum Cat {
Himilayan, Siamese, Caleco,
Persian {
public void someMethod() { ... }
}
}
Класа наследава само от един клас, като наследява всички членове, които не са маркирани като
private.
Shadowed Variables
------------------
In Chapter 5, we saw that a local variable of the same name as an instance variable shadows (hides) the
instance variable.
Similarly, an instance variable in a subclass can shadow an instance variable of the same name in its
parent class
Overriding Methods
------------------
@Override
---------
A common programming error in Java is to accidentally overload a method when trying to override it.
Any difference in the number or type of arguments (the method signature) produces two overloaded
methods instead of a single, overridden method.
The new annotations syntax in Java 5.0 provides a way to get the compiler to help with this problem.
An annotation, as we’ll describe in Chapter 7, allows us to add special markers or metadata to source
code that can be read by the compiler or runtime tools.
One of the standard annotations that Java defines is called @Override and it tells the compiler that the
method it marks is intended to override a method in the superclass.
The compiler then warns if the method doesn’t match.
In a previous section, we mentioned that overloaded methods are selected by the compiler at compile
time. Overridden methods, on the other hand, are selected dynamically at runtime.
Even if we create an instance of a subclass our code has never seen before (perhaps a new class loaded
over the network), any overriding methods that it contains are located and used at runtime, replacing
those that existed when we last compiled our code.
Интересно, ако отнякъде се появи jar, който съдържа екстенднат клас и оверрайднат метод, на
класа от първия jar, то тогава рънтайм ще се прецени да се вземе новия екстенднат клас.
final methods and performance
-----------------------------
Ако декларираме някакъв метод final, то той не може да бъде overridе-нат от друг клас и метод.
We have seen final used with variables to effectively make them constants. When applied to a method,
final means that its implementation is constant—no overriding allowed.
final can also be applied to an entire class, which means the class can’t be subclassed.
Exceptions and overridden methods
---------------------------------
class Animal {
Animal create() { ... }
}
class Mammal extends Animal {
Mammal create() { ... }
}
Casting
-------
A cast explicitly tells the compiler to change the apparent type of an object reference. The main use for
casts is when an object is temporarily assigned to a more general type.
Основното използване на case е когато обекта е назначен към по-генерален тип обект.
For example, if a String were assigned to a variable of type Object, to use it as a String again, we’d have
to perform a cast to get it back.
В случая компилатора ще разпознае декларирания тип на променливата (Object), но няма да
разпознае, че има String в нея.
В Java кастването се проверява и в compile time и във runtime.
Attempting to cast an object to an incompatible type at runtime results in a ClassCastException.
Only casts between objects in the same inheritance hierarchy (and, as we’ll see later, to appropriate
interfaces) are legal in Java and pass the scrutiny of the compiler and the runtime system.
Casts in Java affect only the treatment of references; they never change the form of the actual object.
This is an important rule to keep in mind.
You never change the object pointed to by a reference by casting it; you change only the compiler’s (or
runtime system’s) notion of it.
- същото се отнася и ако имаме изричнo викане на super като първи statement.
- ако първия стейтмънт е викане на Overloaded конструктор с this, то тогава Java извиква избрания
конструктор и след неговото връщане, продължава с изпълнението на кода от настоящия
конструктор. Викането на super конструктора ще се случи по време на изпълнението на Overloaded
конструктора.
A method in Java can be declared with the abstract modifier to indicate that it’s just a prototype. An
abstract method has no body; it’s simply a signature declaration followed by a semicolon.
You can’t directly use a class that contains an abstract method; you must instead create a subclass that
implements the abstract method’s body:
In Java, a class that contains one or more abstract methods must be explicitly declared as an abstract
class, also using the abstract modifier:
abstract classVaporClass {
...
abstract void vaporMethod( String name );
...
}
An abstract class can contain other nonabstract methods and ordinary variable declarations, but it can’t
be instantiated.
To be used, it must be subclassed and its abstract methods must be “overridden” with methods that
implement a body.
Not all abstract methods have to be implemented in a single subclass, but a subclass that doesn’t
override all its superclass’s abstract methods with actual, concrete implementations must also be
declared abstract.
Abstract classes provide a framework for classes that is to be “filled in” by the implementer.
The java.io.InputStream class, for example, has a single abstract method called read().
Various subclasses of InputStream implement read() in their own ways to read from their own sources.
The rest of the InputStream class, however, provides extended functionality built on the simple read()
method.
A subclass of InputStream inherits these nonabstract methods to provide functionality based on the
simple read() method that the subclass implements.
Interfaces
==========
Лист от методи, които дефинират някакво поведение на обект. т.е. това е като значка в скаутските
организации. ако можеш да палиш огън и опъваш палатка, значи имаш две значки и това са
конкретни умения, което ти имаш като част от групата.
Интерфейсите се декларират към класовете в compile time.
Типа на интерфейса се държи като тип на класа:
- могат да се дефинират променливи, които да са от типа на интерфейса
- могат да се дефинират аргументи към методи, които приемат типа на интерфейса
- могат да се специфицират return type-ове на методи, които да са от типа на интерфейса
т.е. само обект, който имплементира интерфейса може да приеме тази роля.
В този смисъл интерфейсите са обратни на нормалната йерархия от класове.
Те прекъсват йерархията, която казва какво дадения item/обект е, със това какво може да прави.
Всмисъл аз съм историк, но мога да програмирам.
Класа може да имплементира колкото си иска интерфейси.
Това до някаква степен замества множественото наследяване, което го има в други езици.
Интерфейса изглежда като абстрактен клас. Методи без body, само име и аргументи.
Методите на интерфейса винаги са публични.
Тук дават интересен пример с клас Превозно средство, който има методи (старт двигател, стоп
двигател, завой, стоп), и този интерфейс се имплементира от класове: Автомобил, и Градинска
косачка.
Interfaces as Callbacks
-----------------------
Интерфейсите могат да се използват за имплементиране на callbacks. Това е когато обекта предава
референция към един или няколко от неговите методи към друг обект.
Callback-а се появява когато извикания обект последователно извиква един от своите методи.
В C и C++ това се прави с т.н. function pointers, а в Java се използват интерфейси.
По-генерално, тази концепция е екстендната в Java към конценпцията за events, в които listener
обекта регистрира event източници.
Аз съм обект и викам друг метод от друг обект > предавам му референция към някои от моите
методи > другия метод изпълнява някакъв код,след което вика референцията, която му е
предадена. ??? как обаче се използват интерфейсите за това.
interface TextReceiver {
void receiveText( String text );
}
class TextSource {
TextReceiver receiver;
TextSource( TextReceiver r ) {
receiver = r;
}
Interface Variables
-------------------
Въпреки, че интерфейсите ни позволяват да специфицираме поведение без имплементация, има
едно изключение.
Интерфейса може да съдържа константи (static final variables), които могат да реферирани
директно през името на интерфейса, и ще се появат във всеки клас, който имплементира
интерфейса.
Това позволява константите да бъдат пакетирани заедно с методите на интерфейса и така да се
използват заедно.
interface Scaleable {
static final int BIG = 0, MEDIUM = 1, SMALL = 2;
void setScale( int size );
}
Технически не е грешно да се използва така, но откакто Java добавя enumerations и static imports,
това се обезмисля.
Още повече, че тези константи могат да объркат хората, които имплементират интерфейса. И не
могат да се махнат.
По добре е да се използва енумерация със собствен клас в който има константи, след което да се
направи static import.
// usage
static import mypackage.SizeConstants;
...
setSize( MEDIUM );
Flag Interfaces
---------------
Понякога напълно празен интерфейс може да случи за маркер, че класа има специфично
пропърти.
Това е като инструкция към java компилатора. Примерно java.io.Serializeable interface казва на Java,
че искаме този клас да може да се сериализира по някакъв начин.
В по-новите версии на Java това става излишно, тъй като се използват анотации за тази цел.
Subinterfaces
-------------
По същия начин какво клас екстендва друг клас, така и интерфейса може да екстендне друг
интерфейс.
Интерфейс субтиповете са назначими към техните супертипове, по същия начин както и класовете.
Compilation Units
-----------------
The compiler relies on the names of source files to find and compile dependent classes.
There can be only one package statement, and it applies to the entire file.
Package names are hierarchical in nature, using a dot-separated naming convention.
Names
-----
By default, package name components correspond to directory names and serve as a unique path for
the compiler and runtime systems to locate Java source files and classes.
Но освен за локализация, java не създава друг вид релация между пакетите (както е при
класовете). Няма такова нещо като подпакет subpackage.
Тези класове, на които не сме им дали имена попадат в един голям анонимен пакет.
Class Visibility
----------------
By default, a class is accessible only to other classes within its package.
To be used outside of its package, a class must be declared as public
Това става като интерфейс към външния свят. Тоест ние достъпваме пакета чрез един външен
клас,
а той вече вика останалите които му трябват отвътре. т.е. нещо като боотстрап механизъм.
Интересен пример е как използваме static import. Защото тогава буквално оставаме с
впечатлението, че работим с билдин функции, а те реално са декларирани в пакета, който
импортваме.
// usage
double circumference = 2 * PI * radius;
double length = sin( theta ) * side;
int bigger = max( a, b );
int positive = abs( num );
One of the most important aspects of object-oriented design is data hiding, or encapsulation.
By treating an object in some respects as a “black box” and ignoring the details of its implementation,
we can write more resilient, simpler code with components that can be easily reused.
Array classes live in a parallel Java class hierarchy under the Object class.
java.lang.Object is the ancestor of all objects; it’s the primordial class from which all other classes are
ultimately derived.
Methods defined in Object are, therefore, very important because they appear in every instance of
every class, throughout all of Java
At last count, there were nine public methods and two protected methods in Object. Five of these are
versions of wait() and notify() that are used to synchronize threads on object instances, as we’ll discuss
in Chapter 9.
The remaining four methods are used for basic comparison, conversion, and administration.
Every object has a toString() method that can be called when it’s to be represented as a text value.
PrintStream objects use toString() to print data, as discussed in Chapter 12. toString() is also used
implicitly when an object is referenced in a string concatenation. Here are some examples:
equals() determines whether two objects are equivalent. Precisely what that means for a particular class
is something that you’ll have to decide for yourself.
Two String objects, for example, are considered equivalent if they hold precisely the same characters in
the same sequence:
It is possible in Java to construct two String objects with the same contents that are, nonetheless,
different instances of the String class—although, as we’ll describe later, Java tries to help you avoid that
when it can.
Hashcodes
---------
The hashCode() method returns an integer that is a hashcode for the object.
A hashcode is like a signature or checksum for an object; it’s a random-looking identifying number that is
usually generated from the contents of the object.
The hashcode should always be different for instances of the class that contain different data, but
should be the same for instances that compare “equal” with the equals() method.
Hashcodes are used in the process of storing objects in a Hashtable or a similar kind of collection.
Cloning Objects
---------------
The Java Object class provides the mechanism to make a simple copy of an object including all of its
“shallow” state—a bitwise copy.
What’s so shallow about it? Java has simply copied the values of our variables.
But by default, this capability is turned off.
To make itself cloneable, an object must implement the java.lang.Cloneable interface.
This is a flag interface indicating to Java that the object wants to cooperate in being cloned (the
interface does not actually contain any methods).
If the object isn’t cloneable, the clone() method throws a CloneNotSupportedException.
!!! още един пример за работата на интерфейсите !!!
clone() is a protected method, so by default it can be called only by an object on itself, an object in the
same package, or another object of the same type or a subtype. If we want to make an object cloneable
by everyone, we have to override its clone() method and make it public.
import java.util.HashMap;
public class Sheep implements Cloneable {
HashMap flock = new HashMap();
Classes in Java source code are represented at runtime by instances of the java.lang.Class class.
There’s a Class object for every object type you use; this Class object is responsible for producing
instances of that type.
But you don’t generally have to worry about that unless you are interested in loading new kinds of
classes dynamically at runtime or using a highly abstracted API that wants a “type” instead of an actual
argument.
The Class object is also the basis for “reflecting” on a class to find its methods and other properties,
allowing you to find out about an object’s structure or invoke its methods programmatically at runtime.
We get the Class associated with a particular object with the getClass() method:
We can also get the Class reference for a particular class statically, using the .class notation:
Да се има предвид, че можем да направим инстанция на този клас, само ако има достъпен public
дефолтен конструктор.
Не можем да предадем накакви аргументи на този конструктор.
interface Typewriter {
void typeLine( String s );
...
}
class MyApplication {
...
String outputDeviceName = "Printer";
try {
Class newClass = Class.forName( outputDeviceName );
Typewriter device = (Typewriter)newClass.newInstance();
...
device.typeLine("Hello...");
}
catch ( Exception e ) { ... }
}
!!! Combining these tools, we have the power to load new kinds of classes dynamically.
When combined with the power of interfaces, we can use new data types loaded by a string name in our
applications: !!!
interface Typewriter {
void typeLine( String s );
...
}
class MyApplication {
...
String outputDeviceName = "Printer";
try {
Class newClass = Class.forName( outputDeviceName );
Typewriter device = (Typewriter)newClass.newInstance();
...
device.typeLine("Hello...");
}
catch ( Exception e ) { ... }
}
!!!! Важен пример: Тук ние зареждаме имплементация на Typewriter interface, като само знаем
името на класа.
Ако това име идва от конфигурационен файл или от някъде другъде (примерно да вземем всички
класове, които имплементират дадения интерфейс), то тогава възможностите са много големи.
Този принцип стои в основата на много конфигурационни механизми в Java.
Reflection
==========
In this section, we’ll take a look at the Java Reflection API, supported by the classes in the
java.lang.reflect package.
As its name suggests, reflection is the ability for a class or object to examine itself.
Reflection lets Java code look at an object (more precisely, the class of the object) and determine its
structure.
Within the limits imposed by the security manager, you can find out what constructors, methods, and
fields a class has, as well as their attributes.
You can even change the value of fields, dynamically invoke methods, and construct new objects, much
as if Java had primitive pointers to variables and methods.
And you can do all this on objects that your code has never even seen before.
The Annotations API also has the ability to preserve metadata about source code in the compiled classes
and we can retrieve this information with the Reflection API.
The Reflection API can be used to determine the capabilities of objects at runtime.
It’s used by object serialization to tear apart and build objects for transport over streams or into
persistent storage.
====
Казус:
Ако имаме статик променлива в Абстрактен клас и ако този абстрактен клас се достъпва от
различни класове, дали стойността на статик променливата ще е еднаква.
Аз мисля, че ще е еднаква.