Java 有些类需要初始化,有些类需要don';T

Java 有些类需要初始化,有些类需要don';T,java,class,keyword,Java,Class,Keyword,我已经试着搜索“使用新关键字”的答案,但没有找到我具体问题的答案 为什么有些类必须使用关键字new创建,而有些类则不需要 例如: import java.io.BufferedReader 如果你想使用它,你必须创建一个新的实例 BufferedReader read = new BufferedReader (..............) 但是,例如使用system.console,它也需要导入java.io.console。当您想使用此功能时,只需键入Console c=system.

我已经试着搜索“使用新关键字”的答案,但没有找到我具体问题的答案

为什么有些类必须使用关键字new创建,而有些类则不需要

例如:

import java.io.BufferedReader
如果你想使用它,你必须创建一个新的实例

BufferedReader read = new BufferedReader (..............)
但是,例如使用
system.console
,它也需要导入java.io.console。当您想使用此功能时,只需键入
Console c=system.Console()

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

Thx对于java中的帮助,字段(aka属性)总是与实例或类相关联

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

ClassName instanceName = new ClassName(); 
instanceName.methorOrAttributeNameGoesHere
对于类关联属性,也就是静态属性,可以作为
ClassName.methorOrAttributeNameGoesHere直接访问


这些都是Java的基础知识,您可能应该首先阅读一些关于Java和OOP的好书,如“Head first Java”

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

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

以下是实现
System.console()
的两种方法(完全简化,实际情况并非如此):

(有无限多的方法来实现它,这只是两个例子。你可以通过查看源代码来了解它的复杂性-它类似于(2),每次都返回相同的实例,只是还有一些我不想在这里描述的复杂情况)

在(1)中,如果调用
System.console()
两次,将返回
console的两个不同实例:

System.console() != System.console()
System.console() == System.console()
在(2)中,如果调用
System.console()
两次,将返回
console
的相同实例:

System.console() != System.console()
System.console() == System.console()
我在这里要问的问题是,我是否需要关心返回的是不同的实例还是相同的实例?如果API设计者做了合理的工作,答案可能不是

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

  • 你正在创建的东西可能非常昂贵(速度慢,占用大量资源等),所以你不想创建很多东西
  • 您想要的东西在逻辑上只有一个实例(它是单实例)
他/她希望您在每次调用该方法时创建单独实例的原因有很多,例如:

  • 您不希望所有使用该实例的地方都共享状态。当共享可变类的实例时,您必须担心线程安全等问题
您不希望用户直接调用构造函数的原因有很多:

  • newconsole()
    准确地创建
    Console
    的实例;控制台之类的东西通常依赖于平台,因此在Windows、MacOS等平台上运行时,实际上可能需要返回
    WindowsConsole
    MacConsole
    等的实例。如果
    WindowsConsole
    MacConsole
    扩展
    Console
    ,则可以从
    系统返回其中任何一个实例。Console()
    方法
  • 在Java 7中引入菱形运算符
    之前,有必要在
    new
    语句中包含完整的通用参数,例如
    ArrayList list=new ArrayList();但是,通用方法允许将其写入
    ArrayList list=newList()

    List newList(){return new ArrayList();}
    
  • (有时,您需要很多参数才能传递给构造函数,使用很方便。这与问题中的情况无关,但这是不直接调用构造函数的原因。)

问题是,这些都是内部实现细节,应该进行封装:作为
控制台
类的用户,您不需要关心创建的成本有多高,或者是否存在共享状态:您只需要一个
控制台

这种封装是通过提供类似
System.console()的方法来实现的:您不需要知道该方法的实现方式是否类似于上述(1)或(2)(或任何其他方法)

此外,如果类最初是像(1)那样编写的,并且这被证明是有问题的,那么它的实现可以更改为(2),而无需您作为
系统
类的用户来更新代码


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

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

java.io.Console类在内部附加了system Console。system类提供了一个静态方法
Console()
,该方法返回Console类的唯一实例。这就是为什么我们使用
Console c=system.Console()


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

静态方法不需要实例
<T> List<T> newList() { return new ArrayList<T>(); }
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");
boolean validName1 = Person.isValidName("LordVoldeMort!!!!!"); //returns false
boolean validName2 = Person.isValidName("HarryPotter2016"); //returns true

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