有些类需要初始化,有些则不需要

时间:2016-01-07 08:41:18

标签: java class keyword

我已经尝试在“使用新关键字”上搜索答案,但未在我的具体问题上找到答案。

为什么必须使用关键字new创建一些类,而有些类

例如:

import java.io.BufferedReader

如果要使用此功能,则必须创建新实例

BufferedReader read = new BufferedReader (..............)

但是例如system.console也需要import java.io.console。如果您想使用此功能,只需输入Console c = system.console()

即可

我是Java和OO编程的初学者,在我的书中找到了几个这样的例子。

帮助

4 个答案:

答案 0 :(得分:1)

在java中,字段(又称属性)始终与实例或类相关联。

可能有很多类的实例,要创建实例,您必须使用new运算符。要访问与实例相关的属性,您需要创建一个,这将作为

进行访问
ClassName instanceName = new ClassName(); 
instanceName.methorOrAttributeNameGoesHere

对于类关联属性,静态属性可以直接访问为ClassName.methorOrAttributeNameGoesHere

这些是Java的基础知识,你可能应该首先阅读一些关于Java和OOP的好书,例如Head First Java'

答案 1 :(得分:1)

对此的简单回答是像new BufferedReader() 这样的实例化总是每次调用它时都会创建一个不同的实例;调用System.console()之类的方法可能会或可能不会为您提供不同的实例。

最终,所有对象都通过new实例化;你可能在代码中看不到它。

以下几种方法可以实现System.console() <(完全简化,实际上并非如此):

// (1) Returns new instance each time
class System {
  static Console console() {
    return new Console();
  }
}

// (2) Returns same instance each time
class System {
  private static final Console CONSOLE = new Console();

  static Console console() {
    return CONSOLE;
  }
}

(有很多方法可以实现它,这些只是两个例子。你可以通过查看源代码看到way it is implemented in OpenJDK - 它类似于(2),因为返回了相同的实例每一次,还有一些我不想在此描述的并发症。

在(1)中,如果您两次调用System.console(),您将获得Console的两个不同实例:

System.console() != System.console()

在(2)中,如果您两次调用System.console(),则会返回Console的同一个实例:

System.console() == System.console()

我在这里要问的问题是我是否需要关心我是否回到不同的实例或同一个实例?答案是可能不是,如果API设计师做得很合理。

关于是否公开创建新Console的决定是由编写类的人做出的。每次调用该方法时,他/她可能不希望您创建不同的实例有多种原因,例如:

  • 您正在创建的东西可能非常昂贵(速度慢,占用大量资源等),因此您不想创建大量资源;
  • 你想要的东西逻辑上只有一个实例(它是一个单例)。

每次调用该方法时,他/她可能希望您创建一个单独的实例有很多原因,例如:

  • 您不希望使用该实例的所有地方共享状态。当共享可变类的实例时,你必须担心线程安全等问题。

您可能不希望用户直接调用构造函数有很多原因:

  • new Console()创建Console 的实例;控制台之类的东西通常与平台有关,因此您可能希望在Windows,MacOS等上运行时返回WindowsConsoleMacConsole等实例。如果WindowsConsole和{{1 }} MacConsole,其中任何一个都可以从Console方法返回。
  • 在Java 7中引入菱形运算符System.console()之前,有必要在<>语句中包含完整的通用参数,例如new;但是,通用方法允许将其写为ArrayList<HashMap<String, List<String>>> list = new ArrayList<HashMap<String, List<String>>>();

    ArrayList<HashMap<String, List<String>>> list = newList()
  • (有时,您需要将大量参数传递给构造函数,并且使用Builder Pattern很方便。这与问题中的案例无关,但它是不直接调用构造函数的原因。)

问题是这些是内部实现细节,应该封装:作为<T> List<T> newList() { return new ArrayList<T>(); } 类的用户,您不应该关心多么昂贵它是创建,还是存在共享状态:你只需要一个Console

通过提供类似Console的方法来实现这种封装:您不需要知道该方法是否像上面的(1)或(2)那样实现(或任何其他方法)。

此外,如果该类最初编写为(1),并且证明存在问题,则其实现可以更改为(2),而作为System.console()类的用户,您需要更新你的代码。

对于初学者来说,这可能有点过于细节,我可以尝试帮助您了解更多;它的长短之处在于,如果你不直接创建实例,有时会更好。

答案 2 :(得分:0)

System.console,console是静态的,这就是为什么我们直接用类名调用它,并且调用非静态方法我们通常使用objectname.methodname。

java.io.Console类在内部附加了系统控制台。系统类提供了一个静态方法console(),它返回了Console类的唯一实例。这就是我们以前做Console c = system.console()的原因;

有关详细信息,请阅读静态类和非静态类方法调用/实例创建。

答案 3 :(得分:0)

静态方法不需要实例,但非静态方法可以。 System.console()是静态的,但new BufferedReader(...).read(...)不是

当方法的结果永远不会根据上下文发生变化时,通常会使用静态方法。例如:

Math.abs(-3); //will always be 3, no matter what

但请考虑这个课程:

public class Person {
  private String name;

  public Person(String name){
      this.name = name;
  }

  public String getName() { 
    return name;
  }

  /*
   * In this world, no special characters are allowed in a person's name
   */
  public static boolean isValidName(String name) {
     if (name.contains("!#$%&(=?") {
        return false;
     }
     return true;
  }

}


Person mySister = new Person("Mary");
Person myBrother = new Person("David");

调用Person.getName()没有任何意义;这就像问“一个人的名字是什么?”没有说明这个人是谁。现在,如果你问我“你姐姐的名字是什么?”,那么我可以致电mySister.getName()并给你一个明智的答案。

回复:你的评论“你怎么知道何时不使用新的”

如果您正在尝试创建一个新的Person对象(想象您刚生了一个孩子),但您想知道您在互联网上找到的那个神奇的名字是否会被当局接受:

boolean validName1 = Person.isValidName("LordVoldeMort!!!!!"); //returns false
boolean validName2 = Person.isValidName("HarryPotter2016"); //returns true

Person myLittleBabySon = new Person("HarryPotter2016"); //Accepted by authorities