Java面向对象设计 – Java内部类类型 您可以在类中的任何位置定义内部类,您可以在其中编写Java语句。 有三种类型的内部类。内部类的类型取决于位置和声明的方式。 成员内部类 局部内部类 匿名内部类 成员内部类 成员内部类在类中声明的方式与声明成员字段或成员方法相同。 它可以声明为public,private,protected或package-level。 成员内部类的实例可以仅存在于其封闭类的实例内。 以下代码创建了一个成员内部类。 class Car { private int year; // A member inner class named Tire public class Tire { private double radius; public Tire(double radius) { this.radius = radius; } public double getRadius() { return radius; } } // Member inner class declaration ends here // A constructor for the Car class public Car(int year) { this.year = year; } public int getYear() { return year; } } 局部内部类 一个局部内部类在块中声明。其范围仅限于声明它的块。 由于其范围限于其封闭块,因此其声明不能使用任何访问修饰符,例如public,private或protected。 通常,在方法内定义局部内部类。但是,它也可以在静态初始化器,非静态初始化器和构造器中定义。 下面的代码显示了一个局部内部类的例子。 import java.util.ArrayList; import java.util.Iterator; public class Main { public static void main(String[] args) { StringList tl = new StringList(); tl.addTitle("A"); tl.addTitle("B"); Iterator iterator = tl.titleIterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } } class StringList { private...
Java面向对象的设计 – Java 内部类 什么是内部类? 作为包的成员的类被称为顶级类。 一个类可以在另一个类中声明。这种类型的类称为内部类。 如果在另一个类中声明的类被显式或隐式声明为static,它被称为嵌套类,而不是内部类。 包含内部类的类称为封闭类或外部类。 例子 下面的代码声明一个内部类。 class Outer { public class Inner { // Members of the Inner class go here } // Other members of the Outer class go here } Outer类是一个顶级类。 Inner类是一个内部类。它是外类的成员。 外层类是Inner类的封闭(外部)类。 内部类可以是另一个内部类的封闭类。内部类的嵌套层次没有限制。 内部类的实例只能存在于其封闭类的实例中。 使用内部类的优点 以下是内部类的一些优点。 在将使用它们的其他类附近定义类。 提供了一个额外的命名空间来管理类结构。 一些设计模式使用内部类更容易实现。 实现回调机制使用内部类是优雅和方便的。它有助于在Java中实现闭包。 访问局部变量的限制 下面的代码演示了访问局部内部类中的局部变量的规则。 main()方法声明两个局部变量x和y。这两个变量都是最终的。 变量x在被初始化之后从不改变,变量y不能被改变,因为它被声明为final。 public class Main { public static void main(String... args) { int x = 1; final int y = 2; class LocalInner { void print() { System.out.println("x = " + x); System.out.println("y = " + y); } } /* * Uncomment the following statement will make the variable x no longer * an effectively final variable and the LocalIneer class will not compile. */ // x = 100; LocalInner...
Java面向对象设计 – Java Objects类 Java在java.util包中有一个实用程序类Objects用于处理对象。 它由所有静态方法组成。 Objects类中的大多数方法都会优雅地处理空值。 以下是类中的方法列表。他们的描述遵循列表。 int compare(T a, T b, Comparator c)如果参数相同,则返回0,否则返回c.compare(a,b)。因此,如果两个参数都为null,则返回0。 boolean deepEquals(Object a, Object b)检查两个对象是否相等。如果两个参数都相等,则返回true。否则,它返回false。如果两个参数都为null,则返回true。 boolean equals(Object a, Object b)比较两个对象是否相等。如果两个参数相等,则返回true。否则,它返回false。如果两个参数都为null,则返回true。 int hash(Object… values)为所有指定的对象生成哈希码。它可以用于计算对象的哈希码,该哈希码基于多个实例字段。 int hashCode(Object o)返回指定对象的哈希码值。如果参数为null,则返回0。 boolean isNull(Object obj)如果指定的对象为null,isNull()方法返回true。否则,它返回false。您还可以使用比较运算符==检查对象是否为null,例如,obj == null返回obj的true为null。 boolean nonNull(Object obj)执行与isNull()方法相反的检查。 T requireNonNull(T obj)T requireNonNull(T obj, String message)T requireNonNull(T obj, Supplier messageSupplier)检查参数是否为null。如果参数为null,它会抛出一个NullPointerException异常。此方法设计用于验证方法和构造函数的参数。第二个版本可以指定当参数为null时抛出的NullPointerException的消息。第三个版本的方法将一个Supplier作为第二个参数。 String toString(Object o)String toString(Object o, String nullDefault)如果参数为null,则toString()方法返回一个“null”字符串。对于非空参数,它返回通过调用参数的toString()方法返回的值。 HashCode 下面的代码演示了如何使用来自Objects类的方法来计算哈希码。 import java.util.Objects; public class Main { public static void main(String[] args) { // Compute hash code for two integers, a char, and a string int hash = Objects.hash(10, 800, "\u20b9", "Hello"); System.out.println("Hash Code is " + hash); } } 上面的代码生成以下结果。 equals 以下代码显示了如何使用Objects类中的equals方法来比较两个对象。 import java.util.Objects; public class Main { public static void main(String[] args) { // Test for equality boolean isEqual =...
Java面向对象设计 – Java Object类 Java在java.lang包中有一个Object类。 所有Java类都直接或间接扩展Object类。 所有Java类都是Object类的子类Object类是所有类的超类。 Object类本身没有超类。 Object类的引用变量可以保存任何类的对象的引用。 以下代码声明对象类型的引用变量obj: Object obj; 方法 Object类有九个方法,可以在Java中的所有类中使用。 public String toString() 它是实现在Object类中,我们可以自定义它。它返回对象的字符串表示形式。通常,它用于调试目的。 public boolean equals(Object obj)它在Object类中实现,我们可以自定义它。它用于比较两个对象的相等性。 public int hashCode()它在Object类中实现,我们可以自定义它。它返回对象的哈希码(整数)值。 protected Object clone() throwsCloneNotSupportedException它不在Object类中实现,我们可以通过覆盖克隆方法来自定义它。它用于创建对象的副本。 protected void finalize() throws Throwable它不是在Object类中实现,我们可以自定义它它在对象被销毁之前被垃圾收集器调用。 public final Class getClass()它在Object类中实现,我们不能自定义它。它返回对对象的Class对象的引用。 public final void notify()它是在Object类中实现的,我们不能自定义它。此方法通知对象的等待队列中的一个线程。 public final void notifyAll()它是在Object类中实现的,我们不能自定义它。此方法通知对象的等待队列中的所有线程。 public final void wait() throws InterruptedExceptionpublic final void wait(long timeout) throws InterruptedException public final void wait (long timeout, int nanos) throws InterruptedException它是在Object类中实现的,我们不能自定义它。使对象的等待队列中的线程等待,无论是否超时。 例子 以下代码显示如何重新实现Object类的toString()方法。 public class Test { public String toString() { return "Here is a string"; } } 什么是对象类? Java中的每个对象都属于一个类。 Object类的getClass()方法返回Class对象的引用。 以下代码显示了如何获取Cat对象的Class对象的引用: Cat c = new Cat(); Class catClass = c.getClass(); Class类是通用的,其形式类型参数是由其对象表示的类的名称。 我们可以使用泛型重写上面的语句。 Class<Cat> catClass = c.getClass();
Java面向对象设计 – Java Object.Equals方法 以下代码显示如何实现equals()和hashCode()方法 class Point { private int x; private int y; public Point(int x, int y) { this.x = x; this.y = y; } /* implement the equals() method */ public boolean equals(Object otherObject) { // Are the same? if (this == otherObject) { return true; } // Is otherObject a null reference? if (otherObject == null) { return false; } // Do they belong to the same class? if (this.getClass() != otherObject.getClass()) { return false; } // Get the reference of otherObject in a SmartPoint variable Point otherPoint = (Point) otherObject; // Do they have the same x and y co-ordinates boolean isSamePoint = (this.x == otherPoint.x && this.y == otherPoint.y); return isSamePoint; } /* *...
Java面向对象设计 – Java初始化块 实例初始化块 实例初始化块用于初始化类的对象。 一个实例初始化程序只是一个类的代码块,但在任何方法或构造函数之外。 实例初始值设定程序没有名称。它的代码只是放置在一个开放大括号和闭包。 例子 下面的代码展示了如何为Test类声明一个实例初始化器。 注意,实例初始化程序在实例上下文中执行,并且关键字this在实例初始化程序中可用。 class Test { private int num; // An instance initializer { this.num = 101; /* Other code for the instance initializer*/ } /* Other code for Test class*/ } 多重实例初始化 我们可以有一个类的多个实例初始化器。对于我们创建的每个对象,它们都以文本顺序自动执行。 所有实例初始值的代码在任何构造函数之前执行。 下面的代码演示了构造函数和实例初始化函数的执行顺序。 public class Main { { System.out.println("Inside instance initializer 1."); } { System.out.println("Inside instance initializer 2."); } public Main() { System.out.println("Inside no-args constructor."); } public static void main(String[] args) { Main m = new Main(); } } 上面的代码生成以下结果。 实例初始化程序不能有return语句。 静态初始化块 静态初始化块也称为静态初始化器。它类似于实例初始化块。 它用于初始化一个类。每个对象执行一个实例初始化器,而当类定义被加载到JVM中时,只对一个类执行一次静态初始化器。 我们需要在其声明的开头使用static关键字。 我们可以在类中有多个静态初始化器。所有静态初始化器都按文本出现的顺序执行,并在任何实例初始化器之前执行。 以下代码演示了何时执行静态初始化程序。 public class Main { private static int num; {// An instance initializer System.out.println("Inside instance initializer."); } // A static initializer. Note the use of the keyword static below. static { num = 2014;...
Java面向对象设计 – Java构造函数 构造函数是用于在对象创建后立即初始化对象的代码块。 构造函数的结构看起来类似于一个方法。 声明构造函数 构造函数声明的一般语法是 <Modifiers> <Constructor Name>(<parameters list>) throws <Exceptions list> { } 构造函数的声明以修饰符开头。 构造函数可以将其访问修饰符作为public,private,protected或package-level(无修饰符)。 构造函数名称与类的简单名称相同。 构造函数名称后面是一对括号,可能包括参数。 可选地,右括号后面可以是关键字throws,其后面是逗号分隔的异常列表。 以下代码显示了声明类Test的构造函数的示例。类的名称和构造函数的名称必须匹配。 public class Test { public Test() { // Code goes here } } 与方法不同,构造函数没有返回类型。 使用构造函数 我们使用一个带有new操作符的构造函数来在创建新实例之后初始化类的实例。 new运算符创建一个对象,构造函数初始化该对象。 以下语句使用Test类的构造函数来初始化Test类的对象: Test t = new Test(); 以下代码显示了如何使用构造函数 class Cat { public Cat() { System.out.println("in constructor..."); } } public class Main { public static void main(String[] args) { // Create a Cat object and ignore its reference new Cat(); // Create another Cat object and store its reference in c Cat c = new Cat(); } } 上面的代码生成以下结果。 重载构造函数 一个类可以有多个构造函数。它们称为重载构造函数。 如果一个类有多个构造函数,它们的数量,顺序或参数类型都必须与其他构造函数不同。 下面的代码声明两个构造函数。一个构造函数不接受参数,另一个接受String参数。 class Car { // Constructor #1 public Car() { System.out.println("A car is created."); } // Constructor #2 public Car(String name)...