笔者带你剖析Java7.x新特性

前言

最近在ITeye上看见一些朋友正在激烈讨论关于Java7.x的一些语法结构,所以笔者有些手痒,特此探寻了7.x(此篇博文笔者使用的是目前最新版本的JDK-7u15)的一些新特性分享给大家。虽然目前很多开发人员至今还在沿用Java4.x(笔者项目至今沿用4.x),但这并不是成为不前进的借口。想了解Java的发展,想探寻Java的未来,那么你务必需要时刻保持一颗永不落后的

 

当然笔者此篇博文不代表官方观点,如果有朋友觉得笔者的话语是妙论,希望指正提出,笔者会在第一时间纠正博文内容。在此笔者先谢过各位利用宝贵的时间阅读此篇博文,最后笔者祝愿各位新年大吉,工作顺利。再次啰嗦一点,SSJ的系列博文,笔者将会在本周更新,希望大家体谅。

 

目录

一、自动资源管理;

二、“<>”类型推断运算符;

三、字面值下划线支持;

四、switch字面值支持;

五、声明二进制字面值;

六、catch表达式调整;

七、文件系统改变;

八、探讨Java I/O模型;

九、Swing Framework(JSR 296规范)支持;

十、JVM内核升级之Class Loader架构调整;

十一、JVM内核升级之Garbage Collector调整(时间仓促,后期讲解);

 

一、自动资源管理

早在7.x版本之前,某些可回收资源比如:I/O链接、DB连接、TCP/UDP连接。开发人员都需要在使用后对其进行手动关闭,如果不关闭或者忘记关闭这些资源,就会长期霸占JVM内部的资源,极大程度上影响了JVM的资源分配。就像内存管理一样,开发人员梦寐以求的就是希望有一天再也无需关注繁琐的资源管理(资源创建、资源就绪、资源回收)。值得庆幸的是7.x为我们带来了一次彻头彻尾改变,我们将再也不必以手动管理我们的资源。

早在Java5.x的时候,Java API为开发人员提供了一个Closeable接口。该接口中包含一个close()方法,允许所有可回收资源的类型对其进行重写实现。7.x版本中几乎所有的资源类型都实现了Closeable接口,并重写了close()方法。也就是说所有可回收的系统资源,我们将不必每次使用完后调用close()方法进行资源回收,这一切全部交接给自动资源管理器去做即可。

例如Reader资源类型继承Closeable接口实现资源自动管理:

public abstract class Reader implements Readable, Closeable

  

当然如果你需要在程序中使用自动资源管理,还需要使用API提供的新语法支持,这类语法包含在try语句块内部。看到这里你可能不禁感叹,try也能支持表达式了,是的7.x确实允许try使用表达式的语法方式实现自动资源管理,但仅限于资源类型。

使用try表达式实现自动资源管理:

try(BufferedReader reader = new BufferedReader(new FileReader("路径"));)
{
	//...
}
catch(Exception e)
{
	e.printStackTrace();
}

  

 二、“<>”类型推断运算符

Java5.x新增了许多新的功能,在这些新引入的功能中,泛型最为重要。泛型是一种新的语法元素,泛型的出现导致整个Java API都发生了变化(比如:Java集合框架就使用了泛型语法)。

在泛型没有出现之前,我们都是将Object类作为通用的任意数据类型使用。因为在Java语言中,Object类是所有类的超类。但是使用Object类作为任意数据类型并不是安全的,因为在很多时候我们需要将Object类型向下转换,在这些转换过程中偶尔也可能出现不匹配的类型转换错误。泛型的出现则很好的解决了Object类型所存在的安全性问题,且泛型还扩展了代码的重用性。

泛型的核心概念就是参数化类型,所谓参数化类型指的就是开发人员可以在外部指定的数据类型来创建泛型类泛型接口和泛型方法。

使用泛型类型示例:

List<String> list = new ArrayList<String>();

  

通过上述程序示例我们可以看出,笔者定义了一个泛型类型为String的List集合。这样一来List集合的泛型参数将会被定义为String类型。但是你有没有想过,使用里氏替换原则或者实例化泛型类型时,其实现可以简化泛型类型声明吗?答案是肯定的,在Java7.x中,允许使用运算符“<>”来做类型推断。也就是说你只需要在声明时标注泛型类型,实现时无需重复标注。

使用“<>”类型推断运算符简化泛型语法:

List<String> list = new ArrayList<>();

  

三、字面值下划线支持

不知道大家有没有过同笔者一样的烦恼,早在Java7.x版本之前,咱们在定义int或者long类型等变量的字面值时,往往会因为其定义的值过长,从而严重影响后续的可读性。如果你也是这么觉得,那么你可以考虑使用Java7.x为字面值操作提供的可读性优化。那便是允许你直接的字面值中使用符号“_”进行切分,这样一来不仅可以提升可读性,还能够清晰的分辨出字面值的长度。当然程序运行时自然会将“_”符号进行提取再做运算。

使用“_”符号进行字面值可读性优化:

int money = 100_000_000;

  

四、switch字面值支持

Java一共为开发人员提供了2种多路分支语句,一种是大家常用的if-else,另一种则是switch语句。早在Java7.x版本之前,switch语句表达式值只能定义byteshortintchar等4类型,且该语句表达式值只能匹配一个,故不能重复。但是Java7.x的到来允许switch定义另一种全新的表达式值,那就是String类型。

使用String类型作为Switch表达式值:

switch("a")
{
	case "a":
		System.out.println("a");
		break;
	case "b":
		System.out.println("b");
}

 

五、声明二进制字面值

 JavaC语言、C++语言直接相关。Java语言继承了C语言的语法结构,而OMT(Object Modeling Technique,对象模型)则是直接从C++语言改编而来的。所以早在Java7.x版本之前,开发人员只能够定义十进制、八进制、十六进制等字面值。但是现在你完全可以使用“0b”字符为前缀定义二进制字面值。
定义二进制字面值:

int test = 0b010101; 

 

当然这里笔者需要提示你的是,虽然咱们可以直接在程序中定义二进制字面值。但是在程序运算时,仍然会将其转换成十进制展开运算和输出。

 

六、catch表达式调整

谈到catch语句的时候,不得不提到try语句,因为它们彼此之间存在相互依赖、相互关联的关系。在Java程序中捕获一个异常采用的是try和catch语句,try语句里面所包含的代码块都是需要进行异常监测的,而catch语句里面所包含的代码块,则是告诉程序当异常发生的时候所需要执行的异常处理

谈到捕获异常,在Java7.x之前有2种方式。第一种是采用定义多个catch代码块,另外一种则是直接使用Exception(可恢复性异常超类)进行捕获。但是现在,如果你觉得不想笼统的将所有异常定义为Exception进行捕获,或者纠结于反复定义catch代码块,那么你完全可以采用Java7.x的catch表达式调整。Java7.x允许你在catch表达式内部使用“|”运算符匹配多个异常类型,当触发异常时,异常类型将自动进行类型匹配操作。

使用“|”运算符定义catch表达式:

try 
{
	//...
}
catch (SQLException | Exception e) 
{
	e.printStackTrace();
}

 

七、文件系统改变

既然本章节咱们已经谈到了Java的文件系统(FileSystem),那么必然同样也会关联到I/O技术。其实所谓I/O(Input/Output)指的就是数据输入/输出的过程,我们称之为流(数据通信通道)这个概念。比如当Java应用程序需要读取目标数据源的数据时,则开启输入流。需要写入时,则开启输出流。数据源允许是本地磁盘、内存或者是网络中的数据。

向目标数据源读取数据:

 

向目标数据源写入数据:

Java的文件系统主要由java.io及java.nio两个包内的组件构成早在Java7.x之前,文件的操作一向都比较棘手。当然笔者这里提出的棘手,更多的是指向Java API对文件的管理的不便。比如咱们需要编写一个程序,这个程序的功能仅仅只是拷贝文件后进行粘贴。但就是连这样简单的程序逻辑实现,开发人员动则都需要编写几十行有效代码

使用Java File API操作文件核心示例:

/* 复制目标数据源数据 */
BufferedInputStream reader = new BufferedInputStream(
		new FileInputStream(COPYFILEPATH));
byte[] content = new byte[reader.available()];
reader.read(content);

/* 将复制数据粘贴至新目录 */
BufferedOutputStream write = new BufferedOutputStream(
		new FileOutputStream(PASTEFILEPATH));
write.write(content);

 

通过上述程序示例我们可以看出,仅仅只是编写一个简单的文件复制粘贴逻辑,我们的代码量都大得惊人。如果你也认同上述程序的繁琐,那么你完全有必要体验下Java7.x对文件系统的一次全新改变

Java7.x推出了全新的NIO.2 API以此改变针对文件管理的不便,使得在java.nio.file包下使用Path、Paths、Files、WatchService、FileSystem等常用类型可以很好的简化开发人员对文件管理的编码工作。

咱们就先从Path接口开始进行讲解吧。Path接口的某些功能其实可以和java.io包下的File类型等价,当然这些功能仅限于只读操作。在实际开发过程中,开发人员可以联用Path接口和Paths类型,从而获取文件的一系列上下文信息。

Path接口常用方法如下:

方法名称方法返回类型方法描述
getNameCount()int获取当前文件节点数
getFileName()java.nio.file.Path获取当前文件名称
getRoot()java.nio.file.Path获取当前文件根目录
getParent()java.nio.file.Path获取当前文件上级关联目录

 

联用Path接口和Paths类型获取文件信息:

@Test
public void testFile() {
	Path path = Paths.get("路径:/文件");
	System.out.println("文件节点数:" + path.getNameCount());   
	System.out.println("文件名称:" + path.getFileName());   
	System.out.println("文件根目录:" + path.getRoot());   
	System.out.println("文件上级关联目录:" + path.getParent());   
}

 

通过上述程序示例我们可以看出,联用Path接口和Paths类型可以很方便的访问到目标文件的上下文信息。当然这些操作全都是只读的,如果开发人员想对文件进行其它非只读操作,比如文件的创建、修改、删除等操作,则可以使用Files类型进行操作。

Files类型常用方法如下:

方法名称方法返回类型方法描述
createFile()java.nio.file.Path在指定的目标目录创建新文件
delete()void删除指定目标路径的文件或文件夹
copy()java.nio.file.Path将指定目标路径的文件拷贝到另一个文件中
move()java.nio.file.Path将指定目标路径的文件转移到其他路径下,并删除源文件

 

使用Files类型复制、粘贴文件示例:

Files.copy(Paths.get("路径:/源文件"), Paths.get("路径:/新文件"));

 

通过上述程序示例我们可以看出,使用Files类型来管理文件,相对于传统的I/O方式来说更加方便简单。因为具体的操作实现将全部移交给NIO.2 API,开发人员则无需关注。

Java7.x还为开发人员提供了一套全新的文件系统功能,那就是文件监测。在此或许有很多朋友并不知晓文件监测有何意义及目,那么请大家回想下调试成热发布功能后的Web容器。当项目迭代后并重新部署时,开发人员无需对其进行手动重启,因为Web容器一旦监测到文件发生改变后,便会自动去适应这些“变化”并重新进行内部装载。Web容器的热发布功能同样也是基于文件监测功能,所以不得不承认,文件监测功能的出现对于Java文件系统来说是具有重大意义的。

 

提示

就事论事而言,Java7.x的文件监测功能多少存在一些性能和功能上的缺陷。但随着Java后续版本的迭代,笔者相信会有那么一天,足以让某些整天在论坛上打口水战的“高手”们闭嘴。

 

如果在程序中需要使用Java7.x的文件监测功能,那么我们务必需要了解java.nio.file包下的WatchService接口。WatchService接口不仅作为监测服务,还管理着具体的监控细节

我们可以通过使用java.nio.file包下的FileSystems类型,并调用FileSystems类型的newWatchService()方法,从而获取到WatchService接口的对象实例。

获取WatchService接口实例:

WatchService watchService = FileSystems.getDefault()
		.newWatchService();

 

文件监测是基于件驱动的,事件触发是作为监测的先决条件。开发人员可以使用java.nio.file包下的StandardWatchEventKinds类型提供的3种字面常量来定义监测事件类型,值得注意的是监测事件需要和WatchService实例一起进行注册

StandardWatchEventKinds类型提供的监测事件:

1、ENTRY_CREATE:文件或文件夹新建事件

2、ENTRY_DELETE:文件或文件夹删除事件

3、ENTRY_MODIFY:文件或文件夹粘贴事件

 

使用WatchService类型实现文件监控完整示例:
@Test
public void testWatch() {
	/* 监控目标路径 */
	Path path = Paths.get("C:/");
	try {
		/* 创建文件监控对象 */
		WatchService watchService = FileSystems.getDefault()
				.newWatchService();

		/* 注册文件监控的所有事件类型 */
		path.register(watchService, ENTRY_CREATE, ENTRY_DELETE,
				ENTRY_MODIFY);

		/* 循环监测文件 */
		while (true) {
			WatchKey watchKey = watchService.take();

			/* 迭代触发事件的所有文件 */
			for (WatchEvent<?> event : watchKey.pollEvents())
				System.out.println(event.context().toString() + " 事件类型:"
						+ event.kind());
			if (!watchKey.reset())
				return;
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

  

通过上述程序示例我们可以看出,使用WatchService接口进行文件监控非常简单和方便。首先我们需要定义好目标监控路径,然后调用FileSystems类型的newWatchService()方法创建WatchService对象。接下来我们还需使用Path接口的register()方法注册WatchService实例及监控事件。当这些基础作业层全部准备好后,我们再编写外围实时监测循环。最后迭代WatchKey来获取所有触发监控事件的文件即可。

 

提示

如果在项目中使用上述程序示例,笔者建议你最好将这段监控代码进行异步化。因为死循环会占用主线程,后续代码将永远得不到执行机会。

 

八、探讨Java I/O模型

在基于分布式的编程环境中,系统性能的瓶颈往往由I/O读写性决定。这是不可否认的事实,也是众多开发人员首要考虑的优化问题。如果在Windows环境下我们使用阻塞I/O模型来编写分布式应用,其维护成本的往往超出你的想象。因为客户端的链接数量直接决定了服务器内存开辟的线程数量 * 2(包含:接受线程、输出线程),并且这些线程是无法采取线程池优化的,因为线程的执行之间大于其创建和销毁时间。长时间的大量并发线程挂起,不仅CPU要做实时任务切换,其整体物理资源都将一步步被蚕食,直至最后程序崩溃。在早期的网络编程中,采取阻塞I/O模型来编写分布式应用,唯一能做性能优化只有采取传统的硬件式堆机。在付出高昂的硬件成本开销时,其项目的维护性也令开发人员头痛。而且在实际的开发过程中,大部分开发人员会选择将项目部署在Linux下运行。跟Windows内核结构不同的是,Linux环境下是没有真正意义上的线程概念。其所谓的线程都是采用进程模拟的方式,也就是伪线程。笔者希望大家能够明白,对于并发要求极高的分布式应用,一旦采用阻塞IO模型编写就等于自寻死路。

Java的I/O模型由同步I/O和异步I/O构成。同步I/O模型包含:阻塞I/O和非阻塞I/O,而在Windows环境下只要调用了IOCP的I/O模型,就是真正意义上的异步I/O。

Java的I/O模型示例图:

 

IOCP(Input/Outut Completion Port,输入/输出完成端口)简单来说是一种系统级高性能异步I/O模型。应用程序中所有的I/O操作将全部委托给操作系统线程去执行,直至最后通知并返回结果。Java7.x对IOCP进行了深度封装,这使得开发人员可以使用IOCP API编写高效的分布式应用。当然IOCP仅限于使用在Windows平台,因而无法在Linux平台上使用它(Linux平台上可以通过Epoll模拟IOCP实现)。

 

提示

有过网络编程经验的开发人员都应该明白,在Windows平台下性能最好的I/O模型是IOCP,Linux平台下则是EPOLL。但是EPOLL并不算真正意义上的异步I/O,EPOLL只是在尽可能的模拟IOCP而已。因为按照Unix网络编程的划分,多路复用I/O仍然属于同步I/O模型,也就是说EPOLL其实是属于多路复用I/O。

简单来说异步I/O的特征必须满足如下2点:

1、I/O请求与I/O操作不会阻塞;

2、并非程序自身完成I/O操作,由操作系统线程处理实际的I/O操作,直至最后通知并返回结果;

 

早在Java4.x的时候,NIO(Java New Input/Output,Java新输入/输出)的出现,使得开发人员可以彻底从阻塞I/O的噩梦中挣脱出来。但编写NIO的成本较大,学习难度也比较高,使得诸多开发人员望而却步(目前比较成熟的NIO Frameworks有:Mina、Netty)。但理解非阻塞I/O的原理还是非常有必要,先来观察下述采用阻塞I/O模式编写的分布式应用示例:

@Test
public void testServer() {
	try {
		ServerSocket server = new ServerSocket(8888);
		Socket clist = server.accept();
		BufferedReader reader = new BufferedReader(new InputStreamReader(
				clist.getInputStream()));
		
		/* 未收到I/O请求时阻塞 */
		System.out.println(reader.readLine());
	} catch (Exception e) {
		e.printStackTrace();
	}
}

  

I/O的工作内容我们可以根据其性质划分为2部分:I/O请求和I/O操作。上述程序示例我们采用的是阻塞I/O模型,可以很明确的发现当客户端成功握手服务端后,如果服务端并没有收到客户端的I/O请求,服务端会在reader.readLine()方法处阻塞。直到成功接收到I/O请求后,服务端才会开始执行实际的I/O操作。运用阻塞I/O模式进行分布式编程,为了保证服务端与客户端集合的成功会话,我们不得不为每一条客户端连接都开辟独立的线程执行I/O操作。当然在实际的开发过程中,或许已经没有开发人员会做这么荒唐的事情了。

非阻塞I/O和阻塞I/O最大的不同在于,非阻塞I/O并不会在I/O请求时产生阻塞。也就是说如果服务端没有收到I/O请求时,非阻塞I/O会持续轮循I/O请求,当有请求进来后就开始执行I/O操作并阻塞请求进程。Java7.x允许开发人员使用IOCP API进行异步I/O编程,这使得开发人员不必再关心I/O是否阻塞。因为应用程序中所有的I/O操作将全部委托给操作系统线程去执行,直至最后通知并返回结果。

 

九、Swing Framework(JSR 296规范)支持

笔者其实对Swing非常厌恶,如果可以的话笔者希望Oracle能够废除掉Swing这项技术。早在08年的时候笔者由于项目需要,曾饱受Swing的折磨。繁琐的布局、组件加载优化、冗长代码维护这些令人痛苦和发指的问题,笔者相信使用过Swing的人开发人员都能发出相同的感叹。

早期的Java GUI(图形用户界面)主要由AWT技术主导,但随着用户对胖客户端技术的丰富度要求逐渐提高,AWT主键逐渐被Swing替代。Swing其实继承于AWT,并提供有更加绚丽的视图组件效果。何况相对于重量级的AWT组件来说,Swing显得更加轻量

笔者刚才说过,Swing虽然相对于AWT来说组件内容更加丰富,但仍然掩盖不了其繁琐的操作实现。如果对组件性能有过高要求,或者需要实现快速开发,笔者更建议你使用SWT或者JFace技术(无需指望使用IDE工具进行可视化编程,因为这纯粹是吃力不讨好)。因为这2种技术可以看成是Swing的过渡,且相对Swing来说性能和丰富度更加优秀。

既然Java7.x对Swing仍不忘眷顾优化,那希望大家还是支持一下吧。从官方声明可以看出,JSR 296规范的目标是简化Swing的开发难度,且提供有更加丰富的组件资源。如果对于从未接触过Swing编程的开发人员,笔者倒是建议你尝试一下,或许你并不反感。

 

十、JVM内核升级之Class Loader架构调整

类装载器(Class Loader)属于JVM体系结构的重要组成部分,它是将Java类型装载进JVM内部的关键一环。它使得Java类型可以动态的被装载到JVM内部解释并运行。
在JVM内部存在着2种类型的类装载器:非自定义类装载器和自定义类装载器 。非自定义类装载器负责装载Java API中的类型及Java程序中的类型,而自定义类装载器能够使用自定义的方式来装载其类型。不同类型的类装载器所装载的类型将被存放于JVM内部不同的命名空间中。
非自定义类装载器由JVM内部3个核心类装载器构成:
1、BootStrap ClassLoader;
2、ExtClassLoader;
3、AppClassLoader;

 

BootStrap ClassLoader也称为启动类装载器,它是JVM内部最顶层的类装载器。BootStrap ClassLoader主要负责装载核心Java API中的类型。ExtClassLoader负责装载扩展目录下的类型。AppClassLoader则负责装载ClassPath(Java应用类路径)下指定的所有类型。其中ExtClassLoader和AppClassLoader都属于BootStrap ClassLoader的派生类装载器。

在Object内部封装着一个通过JNI(Java Native Interface,Java本地接口)方式调用的getClass()本地方法,该方法返回一个Class类型。对于开发人员而言,允许直接调用其getClassLoader()方法获取类装载器实例。

使用getClassLoader()方法获取类装载器:

@Test
public void testClassLoader() throws Exception {
	/* BootStrap ClassLoader装载Java API中的类型 */
	ClassLoader loader = System.class.getClassLoader();
	System.out.println(null != loader ? loader.getClass().getName()
			: loader);

	/* ExtClassLoader装载扩展目录下的类型 */
	System.out.println(CollationData_ar.class.getClassLoader().getClass()
			.getName());

	/* AppClassLoader装载ClassPath下指定的所有类型 */
	System.out.println(this.getClass().getClassLoader().getClass()
			.getName());
}

 

通过上述程序示例我们可以看出,System类型是被BootStrap ClassLoader所装载的。但程序的输出结果却是Null,当然这并不代表BootStrap ClassLoader不存在。因为BootStrap ClassLoader不是采用Java语言编写,而是由C++语言编写并嵌入在JVM内部,所以开发人员无法获取其实例。CollationData_ar类型属于jre\lib\ext目录下的派生类,由ExtClassLoader装载。当前类则由AppClassLoader负责装载。
在此笔者要提示大家,ExtClassLoader和AppClassLoader都是采用Java语言编写。所以ExtClassLoader和AppClassLoader本身也都是Java类型,都会被最顶层的类装载器BootStrap ClassLoader装载,最后才会装载各自管辖范围内的类型。
谈到ClassLoader的架构,我们不得不提及双亲委派模型。在JVM内部,类装载器装载类型所采用的便是双亲委派模型机制。比如AppClassLoader需要将一个类型装载进JVM内部,首先其自身并不会立即装载,而是将目标类型委派给上一级,也就是ExtClassLoader。ExtClassLoader接着再继续委派给BootStrap ClassLoader。在JVM内部最顶层的类装载器就是BootStrap ClassLoader,首先由它负责装载目标类型及其关联或依赖的所有类型。如果BootStrap ClassLoader装载失败,则退回给ExtClassLoader装载。如果ExtClassLoader也无法装载,最后只能退回给AppClassLoader继续装载。最后当AppClassLoader都无法装载的时候,便会抛出ClassNotFoundException异常(开发人员可以在捕获ClassNotFoundException异常的时候重写ClassLoder类型的findClass()方法实现自定义类型装载)。

类装载器架构示例:

 

类装载器除了需要负责类型的装载,还需要负责验证目标类型的正确性、属性内存分配、解析符号引用等操作。JVM通过装载、连接和初始化一个Java类型,使其可以被运行时的Java应用程序所使用。其中装载就是把二进制形式的Java类型写入JVM内部。连接则是把已经写入进JVM中的二进制形式的类型合并到JVM的运行时状态中去。然而连接阶段又分成了3个步骤:验证、准备和解析。“验证”步骤确保了Java类型的数据格式,“准备”步骤则负责为目标类型分配所需的内存空间,“解析”步骤负责把常量池中的符号引用转换为直接使用。“验证”和“解析”这2个步骤都是为最后的初始化工作做准备。

类型生命周期示例:

 

Java7.x在上述ClassLoader架构的基础之上,进行了一些细微调整。在早期开发人员如果想要实现自定义类装载器,恐怕只能实现ClassLoader类型并重写其findClass()方法。但由于findClass()方法是按照串行结构的方式执行,或许是出于对性能和安全的考虑。Java7.x提供了一个拥有并行执行能力的增强实现,这样一来自定义类装载器便可以通过异步方式对类型进行装载。

 

提示

关于自定义类装载器本章笔者将不再继续讲解,如果有兴趣的朋友可以以邮件的形式告知笔者,笔者会为你提供帮助。

 

本章内容到此结束,由于时间仓库,本文或许有很多不尽人意的地方,希望各位能够理解和体谅。关于下一章的内容,笔者打算继续讲解SSJ的相关内容。

学Simulink——基于Simulink的PMSM直接转矩控制(DTC)与SVPWM对比 (如SVM-DTC),将一个控制周期Tc​分为两部分:前Ton​用有效矢量,后Toff​用零矢量,通过调节Ton​/Tc​减小脉动。:根据ψs​扇区(6个)、Te误差(±滞环)、ψs​误差(±滞环)选择8个基本电压矢量(6有效矢量+2零矢量)。:低速时需用电流模型(ψs​=Ls​is​+ψf​),高速时用电压模型(es​=ωψf​),避免纯积分漂移;:基于us​=Rs​is​+Ls​dtdis​​+es​(es​为反电动势),用电压模型估算ψs​; 阅读详情

相关推荐

jdk7 x64位

oracle公司只支持最新版的java的jdk下载,所以jdk7现在在官网已经下不到了,所以提供一个jdk7的64下载

jdk7、jdk8、jdk21及其他版本新特性汇总

jdk7及以上新特性汇总

高格调的博客 3413

ANC 调试详细步骤.docx

TWS蓝牙耳机 ANC 主动降噪详细调试步骤

jdk安装及配置

jdk版本:jdk-7u67-windows-x64 安装配置: 1:根据自己电脑系统x86或者x64下载对应的jdk版本并安装,本人电脑是64位系统,故安装的是64位jdk 2:配置环境 (1)计算机右击属性–高级系统设置–环境变量 (2)在“系统变量”下新建JAVA_HOME何CLASSPATH两个变量名 变量名:JAVA_HOME 变量值:

Asan 1898

java jdk 7_Java之JDK7的新语法探索

Java之JDK7的新语法探索前言感谢! 承蒙关照~字面量:各种精致的表达方式:八进制以0开头,十六进制0X开头,二进制以0B开头.二进制运算时,应该写成这样才直观:&15 -> &0B1111JDK7使用下划线(_)对数据进行分隔.下划线不要这样做:不要用于进制标识和数值之间,不要定义在数值开头和结尾,不要定义在小数点旁边.// 错误0B_1111; _0X32_; 1_...

weixin_31995467的博客 415

JDK7安装教程与配置环境变量

1. JDK7安装教程 2. 配置环境变量(path和classpath)

xfChen2的博客 1409

[附源码]java+ssm计算机毕业设计基于SSM的临沂大学二手交易网站设计与开发2x37x(源码+程序+数据库+部署)

Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。2. 前端:L ayui+css+javascript+jQuery+ElemenUI+highcharts。SSM + mybatis + Maven + JSP 等等组成,B/S模式 + Maven管理等等。2. 使用IDEA/Eclipse/MyEclipse导入项目,修改配置,运行项目;

eggwdd的博客 142

跟着笔者一起剖析Java7.x新特性

前言最近在ITeye上看见一些朋友正在激烈讨论关于Java7.x的一些语法结构,所以笔者有些手痒,特此探寻了7.x(此篇博文笔者使用的是目前最新版本的JDK-7u15)的一些新特性分享给大家。虽然目前很多开发人员至今还在沿用Java4.x(笔者项目至今沿用4.x),但这并不是成为不前进的借口。想了解Java的发展,想探寻Java的未来,那么你务必需要时刻保持一颗永不落后的心。 当然笔者此篇博文并不

萌萌的It人 www.itmmd.com 1692

java标准起草,起草人剖析Java7.x新特性

前言最近在ITeye上看见一些朋友正在激烈讨论关于Java7.x的一些语法结构,所以笔者有些手痒,特此探寻了7.x(此篇博文笔者使用的是目前最新版本的JDK-7u15)的一些新特性分享给大家。虽然目前很多开发人员至今还在沿用Java4.x(笔者项目至今沿用4.x),但这并不是成为不前进的借口。想了解Java的发展,想探寻Java的未来,那么你务必需要时刻保持一颗永不落后的心。当然笔者此篇博文并不代...

weixin_42404710的博客 121

剖析Java7.x新特性

前言 最近在ITeye上看见一些朋友正在激烈讨论关于Java7.x的一些语法结构,所以笔者有些手痒,特此探寻了7.x(此篇博文笔者使用的是目前最新版本的JDK-7u15)的一些新特性分享给大家。虽然目前很多开发人员至今还在沿用Java4.x(笔者项目至今沿用4.x),但这并不是成为不前进的借口。想了解Java的发展,想探寻Java的未来,那么你务必需要时刻保持一颗永不落后的心。   当然笔者

boluobn的专栏 524

JDK7新特性

JDK7新特性 一 JDK7新特性简介 准备 JDK7下载 http://download.java.net/jdk7/ API文档 http://download.java.net/jdk7/docs/api/ 1. 虚拟机 支持动态语言 严格的类文件检查 2. 语言 语法方面的更新 core 类加载器(class-loader)的架构进...

Java 461

JDK7新特性_JDK7的六个新特性

二进制字面量 JDK7开始,终于可以用二进制来表示整数( byte,short,int和long)。使用二进制字面 量的好处是,可以使代码更容易被理解。 语法非常简单,只要在二进制数值前面加 0b或者0B 举例: int x = ob110110 数字字面量可以出现下划线 为了增强对数值的阅读性,如我们经常把数据用逗号分隔一样。JDK7提供了_对数据分隔。 举例: in

辐_射的博客 2427

Java】JDK的下载、安装与部署

这个虽然对很多人来说非常简单,但是还是写写吧,希望能帮助依然有需要的后来者, 记得我第一次配置JDK的时候配置了很久,而且现在每次需要自己重新配置JDK都要看下相应的文章来回忆下,这样才能够完成 JDK配置多了也就渐渐熟悉了。 对于JDK的下载,JAVA的初学者可能就会有疑惑,毕竟这些年JAVA是不停在发展的 按照一些以JDK1.5为蓝本旧式课本甚至JDK1.6为基础的课本上的指示根本就找

编程记录,亲测有效 6345

java7安装教程_JAVA JDK7安装和配置 JAVA JDK7安装配置教程

jdk7 64位7u80 官方正式版(Java SE Development Kit 7)类型:编程辅助大小:139.3M语言:中文 评分:2.6标签:立即下载JAVA JDK7这是一款强大的编程工具,是java革命史上一个重大的突破也是在编程史上又一重大的突破性的发展,相信大家也对这款软件比较了解了,话不多说,西西教大家如何安装JAVA JDK7这款强大的编程工具。教程如下:首先需要去官网下载j...

weixin_33262687的博客 9920

JDK的下载、安装与部署图文教程

  这个虽然对很多人来说非常简单,但是还是写写吧,希望能帮助依然有需要的后来者,   记得我第一次配置JDK的时候配置了很久,而且现在每次需要自己重新配置JDK都要看下相应的文章来回忆下,这样才能够完成   JDK配置多了也就渐渐熟悉了。   对于JDK的下载,JAVA的初学者可能就会有疑惑,毕竟这些年J...

计算机毕业论文源码,学生个人网页制作html源码。贴近用户做网络推广和互联网优化。 1223
上一篇: 详解SSJ(Spring3.x mvc + Spring3.x Core + JPA2.x)轻量级集成开发—第6章 剖析Spring3.x AOP特性02...
下一篇: 详解SSJ(Spring3.x mvc + Spring3.x Core + JPA2.x)轻量级集成开发—第7章 笔者带走进Spring3.x MVC的世界...
gxl1989225
博客等级 码龄17年 14粉丝 30原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值