If we invoke the Getpackage method on the class object, we can get the package object that describes the package in which the class is located (the package class is defined in Java.lang). We can also obtain the package object by calling the static method Getpackage or by calling the static method Getpackages, which returns an array of all the known packages in the system. The GetName method can return the full name of the package.
The use of package objects is completely different from other reflection types, that is, we cannot create or manipulate packages at run time. We can use the package object to get information about the package, such as the purpose of the package, who created the package, the version of the package, and so on. We will defer this to the later discussion of the package in detail.
Name of package
the name of the package should avoid conflict with other packages, so choosing a name that is both meaningful and unique is an important aspect of package design. But programmers around the world are developing packages and there is no way to know who is using the package name, so choosing a unique package name is a challenge. If we are certain that a package is used only within our organization, then we can have internal arbitrators (internal arbiter) to ensure that there is no name conflict between the items.
But for the whole world, this approach is impractical. The identifier of the package is a simple name, and a better way to ensure the package name is to use the Internet domain name. If the name of the company we are working for is MAGIC.LNC and the company's domain name is magi c.com, then the declaration of the property package should be:
Note that the domain name element here is arranged in reverse order of the regular domain name.
If we use this idiom, the package name we use will not conflict with anyone else's package name, except that there may be conflicts within our organization. If there is a real conflict within our Organization (perhaps a large enterprise), then we can use more specific domain names to further qualify. Many large companies have internal subdomains, such as east and Europe, that can be used to further qualify package names:
Package corn. magic.japan.attr;
Using this scenario may make the name of the package very long, but relatively secure. Programmers who use this technique will not choose the same package name, and programmers who do not use this technique will not choose the name we use.
Contents of the Package
the contents of the package should be carefully designed so that it contains only functionally related classes and interfaces. The class in the package is free to access the private members of other classes in the package, and some classes may even have sufficient permissions to access the internal details of other classes, and we need to protect the class members in order to avoid the misuse of class members by such classes. Any member that is not declared private can be accessed by all other types in the same package, so the degree of coupling between any unrelated classes may be higher than we expected.
The package also provides a logical grouping function for programmers looking for useful interfaces and classes. A package made up of unrelated classes makes it difficult for programmers to tell which interfaces and classes are useful, and a logical grouping of classes can help programmers reuse code, because programmers can easily find what they need through logical groupings. If the package contains only the relevant, tightly coupled set of types, it means that we can give the type a more intuitive name, so as to avoid the name conflict.
Packages can be nested. For example, Java.lang is a nested package in which packet Lang is nested in a larger package Java, while the package J Ava contains some other packages. Nesting allows related packages to form a hierarchical naming system.
For example, in order to create a set of packages for adaptive systems such as neural networks and genetic algorithms, we can name the package with a dot-delimited moniker, creating nested packages:
Package adaptive. Neural Net;
The source file containing the statement above is located in the Adaptive.neuralnet package, and the Adaptive.neuralnet package itself is a child of the adaptive package. The adaptive package may contain classes that are related to a common adaptive algorithm, such as a generalization problem statement class or a benchmark class. Packages that are deeper in the hierarchy, such as adaptive. Neu-ralnet or Adaptive.genetic, contain classes that are related to a particular type of adaptive algorithm.
The nesting of packages is only one tool for organizing related packages, and it does not provide any special access rights between packages.
The class code in the Adaptive.genetic package cannot access members with package access in adaptive or adaptive.neuralnet packages, and the package scope applies only to specific packages. Nested packages can group related packages and help programmers find the classes they want more conveniently at the logical level, but beyond that, it does not bring any other benefits.
Notes for Packages
Packages can also have annotations. The problem, however, is that because packages are an organizational structure with no source entities, they are not actually defined, so they cannot be annotated like classes or methods, so the package annotations can only be implemented by annotating the package's declaration statements in the source file. However, only one package declaration in each package can have annotations that work on it.
So how do you annotate a package? In fact, the Java language does not force programmers to use a single annotated package statement rule in some way. The recommended approach is to create a file in the package directory named Package I Nfo.java, where only the package statement and the package annotation are stored, without any additional content. For example, a package Info.java file for a attr package looks like this:
@PackageSpec (Name two "Attr Project", version= "1.0"
@DevelopmentSite ("attr.project.org")
@DevelopmentModel (" Open one Source ")
package attr;
where Packagespec,developmentsite and devel Opmentmodel are used to decorate the annotation types, of course, they have a run-time save policy. Package a Info.java file should be compiled with the other source files in the package.
We recommend that all package-related information be placed in package one info. Java file. If you do this, you can place document comments at the beginning of the file so that they are annotated as package documents.
Access to Packages
when declaring the accessibility of the top-level class and top-level interface in a package, there are two options: Package access (package) and public access rights. Classes or interfaces decorated with public can be accessed by code outside the package, types that are not decorated with public have package scopes: they can be accessed by other code in the same package, but they are hidden for code outside the package, and even for code in the child package. When declaring types, we should only declare those types that other programmers need to use as public, and hide those types that belong to the implementation details of the package. This technology gives us a great deal of flexibility because programmers do not rely on the types of implementation details they cannot access, so when we want to change the implementation details, we are free to change them.
Class members that are not declared as public,protected or private can be accessed directly by any code within the package, but the code outside the package is hidden. In other words, the default access modifier is "package", with the exception of the members of the interface whose default access modifier is "public."
A field or method that is not declared private in the package can be accessed by all other code in the package, so the classes in the same package are considered "friendly" or "trustworthy." This allows us to define an application framework that combines predefined codes (predefined code) and placeholder codes (placeholder code), where the placeholder code is overwritten by subclasses of the Framework class. Predefined code can use package access modifiers so that other collaborative code within the package can access them directly, but for outside users, the code is inaccessible. However, the packages in which the code resides are not trusted and vice versa. For example, code decorated with the package access modifier in the package dit cannot be accessed by code in its child package Dit.dat, and vice versa.
Therefore, each type defines three different contracts:
. Publi. Contract: Defines the primary function of a type.
. Protected contract: Defines the functionality that subclasses can obtain for a specific purpose.
Package contract: Defines the functionality that other code within the package can obtain to implement collaboration between types within a package. All these contracts require careful consideration and design.
Accessibility and Cover methods
Only methods that can be accessed in a superclass can be overridden in subclasses. If a method in a superclass cannot be accessed, the method cannot be overridden in a subclass even if the method in the subclass has the same name as the method. When a method is invoked at run time, the system considers its accessibility and determines which concrete implementation to run it.
The following specially constructed example is explained more clearly. Suppose we declare a abstract-base class in the P1 package:
Package P1;
{AB AB AbAb public
abstract class abstractbase
private void pri ()
{
print ("Stractbase.pri ()"):} void Pac () {print ("Stractbase.pac ()");
}
protected void Pro ()
{
print ("Stractbase.pro ()");
}
public void Pub ()
{
print ("Stractbase.pub ()");}
Public final void Show ()
pri ();
PAC ();
Pro ();
Pub ();
}
}
In this class, we define 4 methods, each with a different access modifier, and the method body simply identifies itself. Method Show calls the 4 methods in turn on the current object, and when applied to different subclass objects, you can tell which implementation of those methods was invoked.
Now we define the class Concretel, which extends the Abstractbase class, but is located in the P2 package:
Package P2;
Import P1. Abstractbase public
class Concretel extends abstractbase{public
void pri () {print ("Concretel.pri ()");}
public void Pac () {print ("Concretel.pac ()");}
public void Pro () {print ("Concretel.pro ()");}
public void Pub () {print ("concretel.pub ()");}
}
The 4 methods in the superclass are declared in the class, and their implementations are changed, and these implementations report that they belong to the Con-cretel class. At the same time, their access rights are changed to public for other code access. Execute the following code
New Concretel (). Show ():
Produces the following output:
Abstractbase.pri ()
Abstractbase.pac ()
Concretel.pro ()
concretel.pub ()
Because the private method PRI cannot be accessed by a quilt class (or other Class), the Show method always invokes the implementation of the PRI method in the Abstractbase class. A PAC method with package access in the Abstractbase class cannot be accessed by Concretel, so the implementation of the PAC method in the Concretel class cannot overwrite the definition in the Abstractbase class. So the Show method calls the Abstractbase.pac method. The Pro method and pub method are both accessible in the Concretel class and can be overwritten, so the show method calls the implementation of the two methods in the Concretel class.
Pick up our full class Concrete2 to extend the class Concretel, and then we put it and Abstractbase class in the same package P1 ':
Package P1;
Import P2. Concretel public
class Concrete2 extends concretel{public
void pri () {print ("Concrete2.pri ()");}
public void Pac () {print ("Concrete2.pac ()");}
public void Pro () {print ("Concrete2.pro ()");}
public void Pub () {print ("concrete2.pub ()");}
}
Because methods in Concretel have public access, they can be accessed in Concrete2, and each method in Concrete2 overrides its corresponding method. In addition, because Concrete2 and ab-stractbase are in the same package, the method Abstractbase.pac can also be accessed in Concrete2, and method Concrete2.pac can be overridden. Call the Show method on the Concrete2 object and print the result as follows:
Abstractbase.pri ()
Concrete2.pac ()
Concrete2. Pro ()
concrete2.pub ()
Finally, we define the class Concrete3 to extend the class Concrete2 and put it in the package P3:
Package P3
Import P1. Concrete2;
public class Concrete3 extends concrete2{public
void pri () {print ("Concrete3.pri ()");}
public void Pac Q{print ("Concrete3.pac ()");}
public void Pro () {print ("Concrete3.pro ()");}
public void Pub () {print ("concrete3.pub ()");}
}
Call the Show method on the Concrete3 object and print the result as follows:
Abstractbase.pri ()
Concrete3.pac ()
Concrete3.pro ()
concrete3.pub ()
Here the method Concrete3.pac appears to override the inaccessible Abstractbase.pac method, but in fact, the method Concrete3.pac overrides the method Concrete2.pac, and method Concrete2.pac overrides the method Abstractbas E.pac, so the method Concrete3.pac indirectly covers the method Abstractbase.pac. By declaring the PAC method as having public access in class Concrete2, you can enable it to be accessed and overwritten by any subclass.
Package Objects and specifications
A package usually implements a specification and usually comes from an organization. The package object differs from other reflection types, cannot be used to create or manipulate packages, but only as a repository of information that provides information about the specifications implemented by the package (the title of the specification, vendor and version number), and information about the package's implementation itself (the package title, vendor, and version number). Although a package usually comes from a single organization, the specifications it implements, such as the statistical analysis library, may be defined by other organizations. A program that uses a package might need to know the version of the specification that the package implements, so that you can use features that are defined only in one version. Similarly, these programs may also need to know which implementation version is provided to it, primarily to address possible defects in different versions. Some of the main methods of the package class allow access to this information:
public stri ng getName (): Returns the name of the package.
. public string Getspecificationtitle p: Returns the caption of the specification implemented by the package, and returns null if the title is unknown.
. public string Getspecificationversion (): Returns a string describing the version information of the specification implemented by the package, or null if the version information is unknown.
. public string Getspecificationvendor Q: Returns the name of the vendor that owns and maintains the specifications implemented by the package and returns null if the vendor is unknown.
. public string Getimplerentationtitle (): Returns the title of the implementation provided by the package, and returns null, public string getimplementationversion () if the title is unknown: Returns a string that describes the version information of the implementation provided by the package, or null if the version information is unknown.
public String Getimplementationvendor (): Returns the name of the Organization (vendor) that provided the implementation, or NULL if the organization is unknown.
For example, extracting this information from the Java.lang package in our system will result in the following:
Specification Title:java Platform API Specification Specification version:1.4 specification Vendor:sun Micro
Systems,inc.
Implementation Title:java Runtime Environment Implementation VERSION:1.5.0_02 implementation Vendor:sun MICR
Osystems,inc.
The canonical version number consists of a non-negative number separated by a period delimiter, such as ' 2.0 ' or ' 11.0.12 '. This pattern allows us to invoke the Iscompatiblewith method to compare the version number of the schema with the version number of the package. The method returns true if the package's version number is greater than or equal to the version number of the descendant. This comparison compares a period-delimited number each time, and if any of these numbers is less than the corresponding position in the version number passed in, the two versions are incompatible. If one version number is longer than the other, the missing part of the short version number is considered zero. For example, if the specification version number of the package is "1.4", and we use the Iscompatiblewith method to compare it to "1.2", "1.3.1", or ". 1.81", then returns true, but if compared to ' 1.4.2 '. or '. 5 ', Then false is returned. The reason for this conclusion is that the comparison mechanism assumes that the canonical version is backward compatible.
The implemented version number does not have a specified format because the different organizations that provide the implementation have different definitions of the implementation version. The only comparison that can be made between the implementation versions is whether the test version is the same, and there is no backward-compatible assumption.
The package can be sealed, which means no more classes are added to the package. An unsealed package can contain classes from several different locations in a class search path, and the contents of a sealed package must come from the same location-either a particular archive or a location specified by a URL. There are two ways to determine whether a package is sealed:
. Public Boolean issealed P: If the package is sealed, return Trueo
. public boolean issealed (URL URL): Returns True if the package is sealed for a given URL, that is, the class in the package can be loaded from this given URL. If the class in the package cannot be loaded from the given URL, or if the package is not sealed, returns false, and the specification and implementation information for the package is usually provided as part of the manifest file that is stored with the package-for example, as part of a manifest file in a Java archive (jar), like the 25.9.2 section. Archive file Java.util.jar "as described in. When the class is loaded in the package, the information is read by the person. The class loader (ClassLoader) can dynamically define a package object for the class it is to load:
. protected Package de platform Nepackage (string name,string spectitle,stringspecversion,string Specvendor, String impltitle, String implversion,string Implvendor, URL sealbase): This method returns a package object that has the given package name and the specification and implementation value set by the corresponding argument. If the parameter sealbase is NULL, then the package is not sealed, otherwise the package is sealed for the URL: The package object of the class must be defined before the class is defined, and the name of the package must be unique in the ClassLoader. If the package name is duplicated with the existing name, a 11ega1argumentexception exception is thrown.
We can invoke the Getpackage method of the class object of the given classes to get the package object of the class. We can also invoke the static side package.getpackage with the given package name to get the package object, or call the static side package.getpackages, which returns the package array of all the packages currently known by the ClassLoader. Both of these methods are related to the classloader of the code that calls them, because the code will call the Get-package or Getpackages method of its classloader. These ClassLoader methods search for a particular class loader and all its parent class loaders, and if no settings are made for the current ClassLoader, the System class loader is used at this time. Note that if the package is unknown, the class loader method returns NULL because no type is loaded in the package at this time.