前言: Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级。在Java Code Geeks上已经有很多介绍Java 8新特性的文章,例如Playing with Java 8 – Lambdas and Concurrency、Java 8 Date Time API Tutorial : LocalDateTime和Abstract Class Versus Interface in the JDK 8 Era。本文还参考了一些其他资料,例如:15 Must Read Java 8 Tutorials和The Dark Side of Java 8。本文综合了上述资料,整理成一份关于Java 8新特性的参考教材,希望你有所收获。

  1. 简介
    ======

毫无疑问,Java 8是Java自Java 5(发布于2004年)之后的最重要的版本。这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。在本文中我们将学习这些新特性,并用实际的例子说明在什么场景下适合使用。

这个教程包含Java开发者经常面对的几类问题:

  • 语言
  • 编译器
  • 工具
  • 运行时(JVM)
  1. Java语言的新特性
    ==============

Java 8是Java的一个重大版本,有人认为,虽然这些新特性领Java开发人员十分期待,但同时也需要花不少精力去学习。在这一小节中,我们将介绍Java 8的大部分新特性。

2.1 Lambda表达式和函数式接口

Lambda表达式(也称为闭包)是Java 8中最大和最令人期待的语言改变。它允许我们将函数当成参数传递给某个方法,或者把代码本身当作数据处理:函数式开发者非常熟悉这些概念。很多JVM平台上的语言(Groovy、Scala等)从诞生之日就支持Lambda表达式,但是Java开发者没有选择,只能使用匿名内部类代替Lambda表达式。

Lambda的设计耗费了很多时间和很大的社区力量,最终找到一种折中的实现方案,可以实现简洁而紧凑的语言结构。最简单的Lambda表达式可由逗号分隔的参数列表、**->**符号和语句块组成,例如:

Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );

在上面这个代码中的参数e的类型是由编译器推理得出的,你也可以显式指定该参数的类型,例如:

Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );

如果Lambda表达式需要更复杂的语句块,则可以使用花括号将该语句块括起来,类似于Java中的函数体,例如:

1.  `Arrays.asList( "a", "b", "d" ).forEach( e -> {`2.   `System.out.print( e );`3.   `System.out.print( e );`4.  `} );`

Lambda表达式可以引用类成员和局部变量(会将这些变量隐式得转换成final的),例如下列两个代码块的效果完全相同:

1.  String separator = ",";2.  Arrays.asList( "a", "b", "d" ).forEach( 3.      ( String e ) -> System.out.print( e + separator ) );

1.  final String separator = ",";2.  Arrays.asList( "a", "b", "d" ).forEach( 3.      ( String e ) -> System.out.print( e + separator ) );

Lambda表达式有返回值,返回值的类型也由编译器推理得出。如果Lambda表达式中的语句块只有一行,则可以不用使用return语句,下列两个代码片段效果相同:

Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );

1.  Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {2.      int result = e1.compareTo( e2 );3.      return result;4.  } );

Lambda的设计者们为了让现有的功能与Lambda表达式良好兼容,考虑了很多方法,于是产生了**函数接口这个概念。函数接口指的是只有一个函数的接口,这样的接口可以隐式转换为Lambda表达式。java.lang.Runnablejava.util.concurrent.Callable是函数式接口的最佳例子。在实践中,函数式接口非常脆弱:只要某个开发者在该接口中添加一个函数,则该接口就不再是函数式接口进而导致编译失败。为了克服这种代码层面的脆弱性,并显式说明某个接口是函数式接口,Java 8 提供了一个特殊的注解@FunctionalInterface**(Java 库中的所有相关接口都已经带有这个注解了),举个简单的函数式接口的定义:

1.  `@FunctionalInterface`2.  `public interface Functional {`3.   `void method();`4.  `}`

不过有一点需要注意,默认方法和静态方法不会破坏函数式接口的定义,因此如下的代码是合法的。

1.  `@FunctionalInterface`2.  `public interface FunctionalDefaultMethods {`3.   `void method();`5.   `default void defaultMethod() {` 6.   `}` 7.  `}`

Lambda表达式作为Java 8的最大卖点,它有潜力吸引更多的开发者加入到JVM平台,并在纯Java编程中使用函数式编程的概念。如果你需要了解更多Lambda表达式的细节,可以参考官方文档。

2.2 接口的默认方法和静态方法

Java 8使用两个新概念扩展了接口的含义:默认方法和静态方法。默认方法使得接口有点类似traits,不过要实现的目标不一样。默认方法使得开发者可以在 不破坏二进制兼容性的前提下,往现存接口中添加新的方法,即不强制那些实现了该接口的类也同时实现这个新加的方法。

默认方法和抽象方法之间的区别在于抽象方法需要实现,而默认方法不需要。接口提供的默认方法会被接口的实现类继承或者覆写,例子代码如下:

1.  `private interface Defaulable {`2.   `// Interfaces now allow default methods, the implementer may or` 3.   `// may not implement (override) them.`4.   `default String notRequired() {` 5.   `return "Default implementation";` 6.   `}` 7.  `}`9.  `private static class DefaultableImpl implements Defaulable {`10.  `}`12.  `private static class OverridableImpl implements Defaulable {`13.   `@Override`14.   `public String notRequired() {`15.   `return "Overridden implementation";`16.   `}`17.  `}`

Defaulable接口使用关键字default定义了一个默认方法notRequired()DefaultableImpl类实现了这个接口,同时默认继承了这个接口中的默认方法;OverridableImpl类也实现了这个接口,但覆写了该接口的默认方法,并提供了一个不同的实现。

Java 8带来的另一个有趣的特性是在接口中可以定义静态方法,例子代码如下:

1.  private interface DefaulableFactory {2.      // Interfaces now allow static methods3.      static Defaulable create( Supplier< Defaulable > supplier ) {4.          return supplier.get();5.      }6.  }

下面的代码片段整合了默认方法和静态方法的使用场景:

1.  `public static void main( String[] args ) {`2.   `Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new );`3.   `System.out.println( defaulable.notRequired() );`5.   `defaulable = DefaulableFactory.create( OverridableImpl::new );`6.   `System.out.println( defaulable.notRequired() );`7.  `}`

这段代码的输出结果如下:

1.  `Default implementation`2.  `Overridden implementation`

由于JVM上的默认方法的实现在字节码层面提供了支持,因此效率非常高。默认方法允许在不打破现有继承体系的基础上改进接口。该特性在官方库中的应用是:给java.util.Collection接口添加新方法,如stream()parallelStream()、**forEach()removeIf()**等等。

尽管默认方法有这么多好处,但在实际开发中应该谨慎使用:在复杂的继承体系中,默认方法可能引起歧义和编译错误。如果你想了解更多细节,可以参考官方文档。

2.3 方法引用

方法引用使得开发者可以直接引用现存的方法、Java类的构造方法或者实例对象。方法引用和Lambda表达式配合使用,使得java类的构造方法看起来紧凑而简洁,没有很多复杂的模板代码。

西门的例子中,Car类是不同方法引用的例子,可以帮助读者区分四种类型的方法引用。

1.  public static class Car {2.      public static Car create( final Supplier< Car > supplier ) {3.          return supplier.get();4.      }              6.      public static void collide( final Car car ) {7.          System.out.println( "Collided " + car.toString() );8.      }10.      public void follow( final Car another ) {11.          System.out.println( "Following the " + another.toString() );12.      }14.      public void repair() {   15.          System.out.println( "Repaired " + this.toString() );16.      }17.  }

第一种方法引用的类型是构造器引用,语法是Class::new,或者更一般的形式:Class::new。注意:这个构造器没有参数。

1.  `final Car car = Car.create( Car::new );`2.  `final List< Car > cars = Arrays.asList( car );`

第二种方法引用的类型是静态方法引用,语法是Class::static_method。注意:这个方法接受一个Car类型的参数。

`cars.forEach( Car::collide );`

第三种方法引用的类型是某个类的成员方法的引用,语法是Class::method,注意,这个方法没有定义入参:

`cars.forEach( Car::repair );`

第四种方法引用的类型是某个实例对象的成员方法的引用,语法是instance::method。注意:这个方法接受一个Car类型的参数:

1.  `final Car police = Car.create( Car::new );`2.  `cars.forEach( police::follow );`

运行上述例子,可以在控制台看到如下输出(Car实例可能不同):

1.  Collided com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d2.  Repaired com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d3.  Following the com.javacodegeeks.java8.method.references.MethodReferences$Car@7a81197d

如果想了解和学习更详细的内容,可以参考官方文档

2.4 重复注解

自从Java 5中引入注解以来,这个特性开始变得非常流行,并在各个框架和项目中被广泛使用。不过,注解有一个很大的限制是:在同一个地方不能多次使用同一个注解。Java 8打破了这个限制,引入了重复注解的概念,允许在同一个地方多次使用同一个注解。

在Java 8中使用**@Repeatable**注解定义重复注解,实际上,这并不是语言层面的改进,而是编译器做的一个trick,底层的技术仍然相同。可以利用下面的代码说明:

1.  `package com.javacodegeeks.java8.repeatable.annotations;`3.  `import java.lang.annotation.ElementType;`4.  `import java.lang.annotation.Repeatable;`5.  `import java.lang.annotation.Retention;`6.  `import java.lang.annotation.RetentionPolicy;`7.  `import java.lang.annotation.Target;`9.  `public class RepeatingAnnotations {`10.   `@Target( ElementType.TYPE )`11.   `@Retention( RetentionPolicy.RUNTIME )`12.   `public @interface Filters {`13.   `Filter[] value();`14.   `}`16.   `@Target( ElementType.TYPE )`17.   `@Retention( RetentionPolicy.RUNTIME )`18.   `@Repeatable( Filters.class )`19.   `public @interface Filter {`20.   `String value();`21.   `};`23.   `@Filter( "filter1" )`24.   `@Filter( "filter2" )`25.   `public interface Filterable {` 26.   `}`28.   `public static void main(String[] args) {`29.   `for( Filter filter: Filterable.class.getAnnotationsByType( Filter.class ) ) {`30.   `System.out.println( filter.value() );`31.   `}`32.   `}`33.  `}`

正如我们所见,这里的Filter类使用@Repeatable(Filters.class)注解修饰,而Filters是存放Filter注解的容器,编译器尽量对开发者屏蔽这些细节。这样,Filterable接口可以用两个Filter注解注释(这里并没有提到任何关于Filters的信息)。

另外,反射API提供了一个新的方法:getAnnotationsByType(),可以返回某个类型的重复注解,例如Filterable.class.getAnnoation(Filters.class)将返回两个Filter实例,输出到控制台的内容如下所示:

1.  filter12.  filter2

如果你希望了解更多内容,可以参考官方文档。

2.5 更好的类型推断

Java 8编译器在类型推断方面有很大的提升,在很多场景下编译器可以推导出某个参数的数据类型,从而使得代码更为简洁。例子代码如下:

1.  `package com.javacodegeeks.java8.type.inference;`3.  `public class Value< T > {`4.   `public static< T > T defaultValue() {` 5.   `return null;` 6.   `}`8.   `public T getOrDefault( T value, T defaultValue ) {`9.   `return ( value != null ) ? value : defaultValue;`10.   `}`11.  `}`

下列代码是**Value**类型的应用:

1.  package com.javacodegeeks.java8.type.inference;3.  public class TypeInference {4.      public static void main(String[] args) {5.          final Value< String > value = new Value<>();6.          value.getOrDefault( "22", Value.defaultValue() );7.      }8.  }

参数**Value.defaultValue()**的类型由编译器推导得出,不需要显式指明。在Java 7中这段代码会有编译错误,除非使用Value.<String>defaultValue()

2.6 拓宽注解的应用场景

Java 8拓宽了注解的应用场景。现在,注解几乎可以使用在任何元素上:局部变量、接口类型、超类和接口实现类,甚至可以用在函数的异常定义上。下面是一些例子:

1.  `package com.javacodegeeks.java8.annotations;`3.  `import java.lang.annotation.ElementType;`4.  `import java.lang.annotation.Retention;`5.  `import java.lang.annotation.RetentionPolicy;`6.  `import java.lang.annotation.Target;`7.  `import java.util.ArrayList;`8.  `import java.util.Collection;`10.  `public class Annotations {`11.   `@Retention( RetentionPolicy.RUNTIME )`12.   `@Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } )`13.   `public @interface NonEmpty {` 14.   `}`16.   `public static class Holder< @NonEmpty T > extends @NonEmpty Object {`17.   `public void method() throws @NonEmpty Exception {` 18.   `}`19.   `}`21.   `@SuppressWarnings( "unused" )`22.   `public static void main(String[] args) {`23.   `final Holder< String > holder = new @NonEmpty Holder< String >();` 24.   `@NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>();` 25.   `}`26.  `}`

ElementType.TYPE_USERElementType.TYPE_PARAMETER是Java 8新增的两个注解,用于描述注解的使用场景。Java 语言也做了对应的改变,以识别这些新增的注解。

  1. Java编译器的新特性
    ===============

3.1 参数名称

为了在运行时获得Java程序中方法的参数名称,老一辈的Java程序员必须使用不同方法,例如Paranamer liberary。Java 8终于将这个特性规范化,在语言层面(使用反射API和Parameter.getName()方法)和字节码层面(使用新的javac编译器以及**-parameters**参数)提供支持。

1.  `package com.javacodegeeks.java8.parameter.names;`3.  `import java.lang.reflect.Method;`4.  `import java.lang.reflect.Parameter;`6.  `public class ParameterNames {`7.   `public static void main(String[] args) throws Exception {`8.   `Method method = ParameterNames.class.getMethod( "main", String[].class );`9.   `for( final Parameter parameter: method.getParameters() ) {`10.   `System.out.println( "Parameter: " + parameter.getName() );`11.   `}`12.   `}`13.  `}`

在Java 8中这个特性是默认关闭的,因此如果不带**-parameters**参数编译上述代码并运行,则会输出如下结果:

Parameter: arg0

如果带**-parameters**参数,则会输出如下结果(正确的结果):

Parameter: args

如果你使用Maven进行项目管理,则可以在maven-compiler-plugin编译器的配置项中配置**-parameters**参数:

1.  <plugin>2.      <groupId>org.apache.maven.plugins</groupId>3.      <artifactId>maven-compiler-plugin</artifactId>4.      <version>3.1</version>5.      <configuration>6.          <compilerArgument>-parameters</compilerArgument>7.          <source>1.8</source>8.          <target>1.8</target>9.      </configuration>10.  </plugin>
  1. Java官方库的新特性
    ===============

Java 8增加了很多新的工具类(date/time类),并扩展了现存的工具类,以支持现代的并发编程、函数式编程等。

4.1 Optional

Java应用中最常见的bug就是空值异常。在Java 8之前,Google Guava引入了Optionals类来解决NullPointerException,从而避免源码被各种null检查污染,以便开发者写出更加整洁的代码。Java 8也将Optional加入了官方库。

Optional仅仅是一个容易:存放T类型的值或者null。它提供了一些有用的接口来避免显式的null检查,可以参考Java 8官方文档了解更多细节。

接下来看一点使用Optional的例子:可能为空的值或者某个类型的值:

1.  Optional< String > fullName = Optional.ofNullable( null );2.  System.out.println( "Full Name is set? " + fullName.isPresent() );        3.  System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) ); 4.  System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );

如果Optional实例持有一个非空值,则**isPresent()**方法返回true,否则返回false;**orElseGet()**方法,Optional实例持有null,则可以接受一个lambda表达式生成的默认值;map()方法可以将现有的Opetional实例的值转换成新的值;**orElse()方法与orElseGet()**方法类似,但是在持有null的时候返回传入的默认值。

上述代码的输出结果如下:

1.  `Full Name is set? false`2.  `Full Name: [none]`3.  `Hey Stranger!`

再看下另一个简单的例子:

1.  Optional< String > firstName = Optional.of( "Tom" );2.  System.out.println( "First Name is set? " + firstName.isPresent() );        3.  System.out.println( "First Name: " + firstName.orElseGet( () -> "[none]" ) ); 4.  System.out.println( firstName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );5.  System.out.println();

这个例子的输出是:

1.  `First Name is set? true`2.  `First Name: Tom`3.  `Hey Tom!`

如果想了解更多的细节,请参考官方文档。

4.2 Streams

新增的Stream API(java.util.stream)将生成环境的函数式编程引入了Java库中。这是目前为止最大的一次对Java库的完善,以便开发者能够写出更加有效、更加简洁和紧凑的代码。

Steam API极大得简化了集合操作(后面我们会看到不止是集合),首先看下这个叫Task的类:

1.  `public class Streams {`2.   `private enum Status {`3.   `OPEN, CLOSED`4.   `};`6.   `private static final class Task {`7.   `private final Status status;`8.   `private final Integer points;`10.   `Task( final Status status, final Integer points ) {`11.   `this.status = status;`12.   `this.points = points;`13.   `}`15.   `public Integer getPoints() {`16.   `return points;`17.   `}`19.   `public Status getStatus() {`20.   `return status;`21.   `}`23.   `@Override`24.   `public String toString() {`25.   `return String.format( "[%s, %d]", status, points );`26.   `}`27.   `}`28.  `}`

Task类有一个分数(或伪复杂度)的概念,另外还有两种状态:OPEN或者CLOSED。现在假设有一个task集合:

1.  `final Collection< Task > tasks = Arrays.asList(`2.   `new Task( Status.OPEN, 5 ),`3.   `new Task( Status.OPEN, 13 ),`4.   `new Task( Status.CLOSED, 8 )` 5.  `);`

首先看一个问题:在这个task集合中一共有多少个OPEN状态的点?在Java 8之前,要解决这个问题,则需要使用foreach循环遍历task集合;但是在Java 8中可以利用steams解决:包括一系列元素的列表,并且支持顺序和并行处理。

1.  `// Calculate total points of all active tasks using sum()`2.  `final long totalPointsOfOpenTasks = tasks`3.   `.stream()`4.   `.filter( task -> task.getStatus() == Status.OPEN )`5.   `.mapToInt( Task::getPoints )`6.   `.sum();`8.  `System.out.println( "Total points: " + totalPointsOfOpenTasks );`

运行这个方法的控制台输出是:

Total points: 18

这里有很多知识点值得说。首先,tasks集合被转换成steam表示;其次,在steam上的filter操作会过滤掉所有CLOSED的task;第三,mapToInt操作基于每个task实例的Task::getPoints方法将task流转换成Integer集合;最后,通过sum方法计算总和,得出最后的结果。

在学习下一个例子之前,还需要记住一些steams(点此更多细节)的知识点。Steam之上的操作可分为中间操作和晚期操作。

中间操作会返回一个新的steam——执行一个中间操作(例如filter)并不会执行实际的过滤操作,而是创建一个新的steam,并将原steam中符合条件的元素放入新创建的steam。

晚期操作(例如forEach或者sum),会遍历steam并得出结果或者附带结果;在执行晚期操作之后,steam处理线已经处理完毕,就不能使用了。在几乎所有情况下,晚期操作都是立刻对steam进行遍历。

steam的另一个价值是创造性地支持并行处理(parallel processing)。对于上述的tasks集合,我们可以用下面的代码计算所有任务的点数之和:

1.  `// Calculate total points of all tasks`2.  `final double totalPoints = tasks`3.   `.stream()`4.   `.parallel()`5.   `.map( task -> task.getPoints() ) // or map( Task::getPoints )` 6.   `.reduce( 0, Integer::sum );`8.  `System.out.println( "Total points (all tasks): " + totalPoints );`

这里我们使用parallel方法并行处理所有的task,并使用reduce方法计算最终的结果。控制台输出如下:

Total points(all tasks): 26.0

对于一个集合,经常需要根据某些条件对其中的元素分组。利用steam提供的API可以很快完成这类任务,代码如下:

1.  `// Group tasks by their status`2.  `final Map< Status, List< Task > > map = tasks`3.   `.stream()`4.   `.collect( Collectors.groupingBy( Task::getStatus ) );`5.  `System.out.println( map );`

控制台的输出如下:

`{CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]}`

最后一个关于tasks集合的例子问题是:如何计算集合中每个任务的点数在集合中所占的比重,具体处理的代码如下:

1.  `// Calculate the weight of each tasks (as percent of total points)` 2.  `final Collection< String > result = tasks`3.   `.stream()                                        // Stream< String >`4.   `.mapToInt( Task::getPoints )                     // IntStream`5.   `.asLongStream()                                  // LongStream`6.   `.mapToDouble( points -> points / totalPoints )   // DoubleStream`7.   `.boxed()                                         // Stream< Double >`8.   `.mapToLong( weigth -> ( long )( weigth * 100 ) ) // LongStream`9.   `.mapToObj( percentage -> percentage + "%" )      // Stream< String>` 10.   `.collect( Collectors.toList() );                 // List< String >` 12.  `System.out.println( result );`

控制台输出结果如下:

[19%, 50%, 30%]

最后,正如之前所说,Steam API不仅可以作用于Java集合,传统的IO操作(从文件或者网络一行一行得读取数据)可以受益于steam处理,这里有一个小例子:

1.  `final Path path = new File( filename ).toPath();`2.  `try( Stream< String > lines = Files.lines( path, StandardCharsets.UTF_8 ) ) {`3.   `lines.onClose( () -> System.out.println("Done!") ).forEach( System.out::println );`4.  `}`

Stream的方法onClose 返回一个等价的有额外句柄的Stream,当Stream的close()方法被调用的时候这个句柄会被执行。Stream API、Lambda表达式还有接口默认方法和静态方法支持的方法引用,是Java 8对软件开发的现代范式的响应。

4.3 Date/Time API(JSR 310)

Java 8引入了新的Date-Time API(JSR 310)来改进时间、日期的处理。时间和日期的管理一直是最令Java开发者痛苦的问题。java.util.Date和后来的java.util.Calendar一直没有解决这个问题(甚至令开发者更加迷茫)。

因为上面这些原因,诞生了第三方库Joda-Time,可以替代Java的时间管理API。Java 8中新的时间和日期管理API深受Joda-Time影响,并吸收了很多Joda-Time的精华。新的java.time包包含了所有关于日期、时间、时区、Instant(跟日期类似但是精确到纳秒)、duration(持续时间)和时钟操作的类。新设计的API认真考虑了这些类的不变性(从java.util.Calendar吸取的教训),如果某个实例需要修改,则返回一个新的对象。

我们接下来看看java.time包中的关键类和各自的使用例子。首先,Clock类使用时区来返回当前的纳秒时间和日期。Clock可以替代System.currentTimeMillis()TimeZone.getDefault()

1.  // Get the system clock as UTC offset 2.  final Clock clock = Clock.systemUTC();3.  System.out.println( clock.instant() );4.  System.out.println( clock.millis() );

这个例子的输出结果是:

1.  `2014-04-12T15:19:29.282Z`2.  `1397315969360`

第二,关注下LocalDateLocalTime类。LocalDate仅仅包含ISO-8601日历系统中的日期部分;LocalTime则仅仅包含该日历系统中的时间部分。这两个类的对象都可以使用Clock对象构建得到。

1.  // Get the local date and local time2.  final LocalDate date = LocalDate.now();3.  final LocalDate dateFromClock = LocalDate.now( clock );5.  System.out.println( date );6.  System.out.println( dateFromClock );8.  // Get the local date and local time9.  final LocalTime time = LocalTime.now();10.  final LocalTime timeFromClock = LocalTime.now( clock );12.  System.out.println( time );13.  System.out.println( timeFromClock );

上述例子的输出结果如下:

1.  `2014-04-12`2.  `2014-04-12`3.  `11:25:54.568`4.  `15:25:54.568`

LocalDateTime类包含了LocalDate和LocalTime的信息,但是不包含ISO-8601日历系统中的时区信息。这里有一些关于LocalDate和LocalTime的例子:

1.  // Get the local date/time2.  final LocalDateTime datetime = LocalDateTime.now();3.  final LocalDateTime datetimeFromClock = LocalDateTime.now( clock );5.  System.out.println( datetime );6.  System.out.println( datetimeFromClock );

上述这个例子的输出结果如下:

1.  `2014-04-12T11:37:52.309`2.  `2014-04-12T15:37:52.309`

如果你需要特定时区的data/time信息,则可以使用ZoneDateTime,它保存有ISO-8601日期系统的日期和时间,而且有时区信息。下面是一些使用不同时区的例子:

1.  // Get the zoned date/time2.  final ZonedDateTime zonedDatetime = ZonedDateTime.now();3.  final ZonedDateTime zonedDatetimeFromClock = ZonedDateTime.now( clock );4.  final ZonedDateTime zonedDatetimeFromZone = ZonedDateTime.now( ZoneId.of( "America/Los_Angeles" ) );6.  System.out.println( zonedDatetime );7.  System.out.println( zonedDatetimeFromClock );8.  System.out.println( zonedDatetimeFromZone );

这个例子的输出结果是:

1.  `2014-04-12T11:47:01.017-04:00[America/New_York]`2.  `2014-04-12T15:47:01.017Z`3.  `2014-04-12T08:47:01.017-07:00[America/Los_Angeles]`

最后看下Duration类,它持有的时间精确到秒和纳秒。这使得我们可以很容易得计算两个日期之间的不同,例子代码如下:

1.  `// Get duration between two dates`2.  `final LocalDateTime from = LocalDateTime.of( 2014, Month.APRIL, 16, 0, 0, 0 );`3.  `final LocalDateTime to = LocalDateTime.of( 2015, Month.APRIL, 16, 23, 59, 59 );`5.  `final Duration duration = Duration.between( from, to );`6.  `System.out.println( "Duration in days: " + duration.toDays() );`7.  `System.out.println( "Duration in hours: " + duration.toHours() );`

这个例子用于计算2014年4月16日和2015年4月16日之间的天数和小时数,输出结果如下:

1.  Duration in days: 3652.  Duration in hours: 8783

对于Java 8的新日期时间的总体印象还是比较积极的,一部分是因为Joda-Time的积极影响,另一部分是因为官方终于听取了开发人员的需求。如果希望了解更多细节,可以参考官方文档。

4.4 Nashorn JavaScript引擎

Java 8提供了新的Nashorn JavaScript引擎,使得我们可以在JVM上开发和运行JS应用。Nashorn JavaScript引擎是javax.script.ScriptEngine的另一个实现版本,这类Script引擎遵循相同的规则,允许Java和JavaScript交互使用,例子代码如下:

1.  ScriptEngineManager manager = new ScriptEngineManager();2.  ScriptEngine engine = manager.getEngineByName( "JavaScript" );4.  System.out.println( engine.getClass().getName() );5.  System.out.println( "Result:" + engine.eval( "function f() { return 1; }; f() + 1;" ) );

这个代码的输出结果如下:

1.  `jdk.nashorn.api.scripting.NashornScriptEngine`2.  `Result: 2`

4.5 Base64

对Base64编码的支持已经被加入到Java 8官方库中,这样不需要使用第三方库就可以进行Base64编码,例子代码如下:

1.  `package com.javacodegeeks.java8.base64;`3.  `import java.nio.charset.StandardCharsets;`4.  `import java.util.Base64;`6.  `public class Base64s {`7.   `public static void main(String[] args) {`8.   `final String text = "Base64 finally in Java 8!";`10.   `final String encoded = Base64`11.   `.getEncoder()`12.   `.encodeToString( text.getBytes( StandardCharsets.UTF_8 ) );`13.   `System.out.println( encoded );`15.   `final String decoded = new String(` 16.   `Base64.getDecoder().decode( encoded ),`17.   `StandardCharsets.UTF_8 );`18.   `System.out.println( decoded );`19.   `}`20.  `}`

这个例子的输出结果如下:

1.  `QmFzZTY0IGZpbmFsbHkgaW4gSmF2YSA4IQ==`2.  `Base64 finally in Java 8!`

新的Base64API也支持URL和MINE的编码解码。
(Base64.getUrlEncoder() / Base64.getUrlDecoder()Base64.getMimeEncoder() / Base64.getMimeDecoder())。

4.6 并行数组

Java8版本新增了很多新的方法,用于支持并行数组处理。最重要的方法是parallelSort(),可以显著加快多核机器上的数组排序。下面的例子论证了parallexXxx系列的方法:

1.  package com.javacodegeeks.java8.parallel.arrays;3.  import java.util.Arrays;4.  import java.util.concurrent.ThreadLocalRandom;6.  public class ParallelArrays {7.      public static void main( String[] args ) {8.          long[] arrayOfLong = new long [ 20000 ];        10.          Arrays.parallelSetAll( arrayOfLong, 11.              index -> ThreadLocalRandom.current().nextInt( 1000000 ) );12.          Arrays.stream( arrayOfLong ).limit( 10 ).forEach( 13.              i -> System.out.print( i + " " ) );14.          System.out.println();16.          Arrays.parallelSort( arrayOfLong );        17.          Arrays.stream( arrayOfLong ).limit( 10 ).forEach( 18.              i -> System.out.print( i + " " ) );19.          System.out.println();20.      }21.  }

上述这些代码使用**parallelSetAll()方法生成20000个随机数,然后使用parallelSort()**方法进行排序。这个程序会输出乱序数组和排序数组的前10个元素。上述例子的代码输出的结果是:

1.  `Unsorted: 591217 891976 443951 424479 766825 351964 242997 642839 119108 552378` 2.  `Sorted: 39 220 263 268 325 607 655 678 723 793`

4.7 并发性

基于新增的lambda表达式和steam特性,为Java 8中为java.util.concurrent.ConcurrentHashMap类添加了新的方法来支持聚焦操作;另外,也为java.util.concurrentForkJoinPool类添加了新的方法来支持通用线程池操作(更多内容可以参考我们的并发编程课程)。

Java 8还添加了新的java.util.concurrent.locks.StampedLock类,用于支持基于容量的锁——该锁有三个模型用于支持读写操作(可以把这个锁当做是java.util.concurrent.locks.ReadWriteLock的替代者)。

java.util.concurrent.atomic包中也新增了不少工具类,列举如下:

  • DoubleAccumulator
  • DoubleAdder
  • LongAccumulator
  • LongAdder
  1. 新的Java工具
    ============

Java 8提供了一些新的命令行工具,这部分会讲解一些对开发者最有用的工具。

5.1 Nashorn引擎:jjs

jjs是一个基于标准Nashorn引擎的命令行工具,可以接受js源码并执行。例如,我们写一个func.js文件,内容如下:

1.  `function f() {` 2.   `return 1;` 3.  `};` 5.  `print( f() + 1 );`

可以在命令行中执行这个命令:jjs func.js,控制台输出结果是:

`2`

如果需要了解细节,可以参考官方文档。

5.2 类依赖分析器:jdeps

jdeps是一个相当棒的命令行工具,它可以展示包层级和类层级的Java类依赖关系,它以**.class**文件、目录或者Jar文件为输入,然后会把依赖关系输出到控制台。

我们可以利用jedps分析下Spring Framework库,为了让结果少一点,仅仅分析一个JAR文件:org.springframework.core-3.0.5.RELEASE.jar

`jdeps org.springframework.core-3.0.5.RELEASE.jar`

这个命令会输出很多结果,我们仅看下其中的一部分:依赖关系按照包分组,如果在classpath上找不到依赖,则显示"not found".

1.  `org.springframework.core-3.0.5.RELEASE.jar -> C:Program FilesJavajdk1.8.0jrelibrt.jar`2.   `org.springframework.core (org.springframework.core-3.0.5.RELEASE.jar)`3.   `-> java.io` 4.   `-> java.lang` 5.   `-> java.lang.annotation` 6.   `-> java.lang.ref` 7.   `-> java.lang.reflect` 8.   `-> java.util` 9.   `-> java.util.concurrent` 10.   `-> org.apache.commons.logging                         not found`11.   `-> org.springframework.asm                            not found`12.   `-> org.springframework.asm.commons                    not found`13.   `org.springframework.core.annotation (org.springframework.core-3.0.5.RELEASE.jar)`14.   `-> java.lang` 15.   `-> java.lang.annotation` 16.   `-> java.lang.reflect` 17.   `-> java.util`
  1. JVM的新特性
    ===========

使用**Metaspace(JEP 122)代替持久代(PermGen space)。在JVM参数方面,使用-XX:MetaSpaceSize-XX:MaxMetaspaceSize代替原来的-XX:PermSize-XX:MaxPermSize**。

  1. 结论
    ======

通过为开发者提供很多能够提高生产力的特性,Java 8使得Java平台前进了一大步。现在还不太适合将Java 8应用在生产系统中,但是在之后的几个月中Java 8的应用率一定会逐步提高(PS:原文时间是2014年5月9日,现在在很多公司Java 8已经成为主流,我司由于体量太大,现在也在一点点上Java 8,虽然慢但是好歹在升级了)。作为开发者,现在应该学习一些Java 8的知识,为升级做好准备。

关于Spring:对于企业级开发,我们也应该关注Spring社区对Java 8的支持,可以参考这篇文章——Spring 4支持的Java 8新特性一览

  1. 参考资料
    ========
  • What’s New in JDK 8

  • The Java Tutorials

  • WildFly 8, JDK 8, NetBeans 8, Java EE

  • Java 8 Tutorial

  • JDK 8 Command-line Static Dependency Checker

  • The Illuminating Javadoc of JDK

  • The Dark Side of Java 8

  • Installing Java™ 8 Support in Eclipse Kepler SR2

  • Java 8

  • Oracle Nashorn. A Next-Generation JavaScript Engine for the JVM

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. Java毕业设计参考文献(推荐109个)

    java毕业设计参考文献一&#xff1a; [1]张永强. 计算机软件Java编程特点及其技术分析[J]. 计算机产品与流通&#xff0c;2019&#xff08;01&#xff09;:23.   [2]王越. JAVA编程语言在计算机软件开发中的应用[J]. 电子技术与软件工程&#xff0c;2019&#xff08;01&…...

    2024/4/24 4:17:24
  2. vue03

    vue-day03 1.watch 案例&#xff1a;百度搜索框 接口&#xff1a;百度&#xff1a;http://suggestion.baidu.com/su?cbcallback&wd123 1.深浅监听 watch:{//浅监听msg(newVal,oldVal){console.log(newVal,oldVal)},//深监听json:{//这个名字不能更改handler(a){consol…...

    2024/4/3 3:51:19
  3. js入门

    js新手入门 js是轻类型&#xff0c;解析型的脚本语言 浏览器不会解析js的注释 js是如何解析的&#xff0c;解析的过程是什么&#xff1f; js被web浏览器所解析 解析的过程分三部&#xff1a;1.语言分析&#xff0c;分析是否有js语法错误。2.预编译&#xff0c;执行之前需要做…...

    2024/4/3 4:29:04
  4. 杰里之AC696 列 系列 SDK1.1.1 打开 PC 模式时某些 U 盘无法读取的处理方法【篇】

    查下主从在线计数cnt...

    2024/4/21 1:01:27
  5. web页面调用本地程序

    最近由于项目需要在web页面中调用本地部署的exe程序&#xff1b;进而对该功能实现做了对应了解&#xff1b;以及存在的问题进行记录。 要实现该功能就不得不说浏览器自定义协议&#xff1b;解决办法&#xff1a;那么它是什么呢&#xff1f; 浏览器自定义协议&#xff1a; 浏…...

    2024/4/3 3:22:47
  6. Java 对HashMap 进行排序的几种场景

    Java中HashMap不同于Array、ArrayList和LinkedLists&#xff0c;它不会维持插入元素的顺序。因此对HashMap排序的掌握很重要。HashMap排序有两个步骤&#xff1a; 1、通过map.entrySet()方法获取键值对;并将键值对传递给链表list&#xff1b;2、自定义比较器来使用Collections…...

    2024/5/4 4:50:24
  7. mybatis判断list是否为空

    前言 <if test"list! null and list.size()>0" >and s.orderstatus in <foreach collection"list" item"item" open"(" close")" separator"," >#{item}</foreach> </if>...

    2024/4/3 3:26:08
  8. arcgis api for javascript 4.16 定位功能的实现

    一、定位功能&#xff0c;应用场景为自定义搜索框&#xff0c;可以用ajax搜索结果&#xff0c;然后单击定位。还有一种是下面说的&#xff0c;在element ui表格中&#xff0c;点击定位按钮&#xff0c;实现地图跳转定位。 二、代码部分。 // 定位功能 locator: async functio…...

    2024/4/6 15:31:01
  9. 杰里之AC696 列 系列 SDK1.1.1 DACR 做 做 linein 输入时没声音的处理方法【篇】

    ...

    2024/4/28 7:50:52
  10. javase学习笔记03

    3.1 面向过程与面向对象 1.面向过程关注于功能和行为 面向对象关注于功能和行为所属的对象。 2.Java 语言&#xff0c;作为面向对象的语言&#xff0c;更多的关注于类的设计&#xff01; 3.面向对象两大元素&#xff1a;类和对象 三大特性&#xff1a;封装、继承、多态、&…...

    2024/4/24 20:08:11
  11. 禅道得使用背诵

    admin&#xff08;管理员&#xff09; 部门&#xff1a;创建部门(需求部门,开发部门,测试部门,项目部门,产品部门) 组织&#xff1a;创建用户(产品经理&#xff0c;项目经理&#xff0c;开发人员&#xff0c;测试人员)&#xff0c;分配权限 产品 模块&#xff1a;添加模块 产品…...

    2024/4/24 20:08:10
  12. roscore提示日志文件超过1G,清理日志文件

    点击这里...

    2024/5/4 2:39:03
  13. for循环-双重for循环

    for循环-双重for循环 1 - 循环 1.1 for循环 语法结构 for(初始化变量; 条件表达式; 操作表达式 ){ //循环体 } | 名称 | 作用 | 初始化变量 | 通常被用于初始化一个计数器&#xff0c;该表达式可以使用 var 关键…...

    2024/5/4 1:52:02
  14. ② EJB有状态的bean

    ② EJB有状态的bean 1.定义 有状态会话bean是一种企业bean的它与客户保持会话状态。有状态会话Bean根据其名声在它的实例变量相关的客户端状态。 EJB容器创建一个单独的有状态会话bean来处理客户端的每个请求。只要请求范围已经结束&#xff0c;statelful会话bean被销毁。类似…...

    2024/5/4 0:11:26
  15. MyBatis----基于代理 Dao 实现 CRUD 操作

    上一篇&#x1f449;:MyBatis----回顾mybatis自定义和环境搭建完善自定义Mybatis的注解开发 文章目录1、mybatis的CRUD-保存操作2、mybatis的CRUD-修改和删除操作3、mybatis的CRUD-查询一个和模糊查询4、mybatis的CRUD-查询返回一行一列和占位符分析5、mybatis的CRUD-保存操作的…...

    2024/4/3 17:05:16
  16. 基于fbprophet的时间序列预测

    基于fbprophet的时间序列预测基于fbprophet的时间序列预测Prophet模型常用参数说明趋势相关周期相关假日相关简单入门误差评估与调参使用训练出来的参数进行最终的预测基于fbprophet的时间序列预测 由于业务的需求&#xff0c;需要对未来一段时间做销量预测&#xff0c;这在过…...

    2024/4/3 17:35:07
  17. 「补课」进行时:设计模式(15)——观察者模式

    1. 前文汇总 「补课」进行时&#xff1a;设计模式系列 2. 观察者模式 2.1 定义 观察者模式&#xff08;Observer Pattern&#xff09;也叫做发布订阅模式&#xff08;Publish/subscribe&#xff09;,它是一个在项目中经常使用的模式&#xff0c;其定义如下&#xff1a; De…...

    2024/4/3 17:14:54
  18. GET(带参) 请求 配置params参数

    import requests #发送网络请求 response requests.get(http://httpbin.org/get?nameJack&age30) print(response.text)输出结果&#xff1a; {"args": {"age": "30", "name": "Jack"}, "headers": {"…...

    2024/4/18 23:47:23
  19. 创建对象

    <script>//创建对象// - 字面量创建let obj {}// - 使用构造函数创建对象let obj2 new Object()// 自定义构造函数构造函数// - 批量创建对象的函数// - 命名首字母大写// - 必须使用new关键字去执行function rapstar(name, Songtitle){this.name namethis.Songtitle …...

    2024/4/3 16:07:20
  20. adb指令

    1.验证adb配置是否成功 指令&#xff1a;adb 2.查看设备 指令&#xff1a;adb devices 3.开启服务 指令&#xff1a;adb start-server 关闭服务 指令&#xff1a;adb kill-server 4.安装软件 指令&#xff1a;adb install apk 路径 adb install ‪E:\ceshi\baidu.apk 覆盖安装 …...

    2024/4/3 12:51:59

最新文章

  1. win10部署本地大模型langchain+ollama

    一、环境 windows10、Python 3.9.18、langchain0.1.9 二、ollama下载 Download Ollama on Windows 0.1.33版本链接https://objects.githubusercontent.com/github-production-release-asset-2e65be/658928958/35e38c8d-b7f6-48ed-8a9c-f053d04b01a9?X-Amz-AlgorithmAWS4-H…...

    2024/5/4 9:10:46
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. OpenCV单通道图像按像素成倍比例放大(无高斯平滑处理)

    OpenCV中的resize函数可以对图像做任意比例的放大(/缩小)处理&#xff0c;该处理过程会对图像做高斯模糊化以保证图像在进行放大&#xff08;/缩小&#xff09;后尽可能保留源图像所展现的具体内容&#xff08;消除固定频率插值/采样带来的香农采样信息损失&#xff09;&#x…...

    2024/5/1 13:33:49
  4. 【虚幻引擎】C++ slate全流程开发教程

    本套课程介绍了使用我们的虚幻C去开发我们的编辑器&#xff0c;扩展我们的编辑器&#xff0c;设置我们自定义样式&#xff0c;Slate架构设计&#xff0c;自定义我们的编辑器样式&#xff0c;从基础的Slate控件到我们的布局&#xff0c;一步步的讲解我们的的Slate基础知识&#…...

    2024/5/1 12:53:48
  5. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/3 11:50:27
  6. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/2 16:04:58
  7. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/5/2 23:55:17
  8. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/5/3 16:00:51
  9. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/5/3 11:10:49
  10. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/3 21:22:01
  11. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/5/3 23:17:01
  12. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/2 23:47:43
  13. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/5/3 13:26:06
  14. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/3 1:55:15
  15. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/5/4 2:14:16
  16. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/3 16:23:03
  17. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/3 1:55:09
  18. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/5/2 8:37:00
  19. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/5/3 14:57:24
  20. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/5/2 9:47:25
  21. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/5/4 2:00:16
  22. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/5/3 22:03:11
  23. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/5/4 9:07:39
  24. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/3 1:54:59
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57