如何把文件从主机中放到虚拟机中?

主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。

享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

运用共享技术有效地支持大量细粒度的对象。

在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。

1、系统中有大量对象。
2、这些对象消耗大量内存。
3、这些对象的状态大部分可以外部化。
4、这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替。
5、系统不依赖于这些对象身份,这些对象是不可分辨的。

唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象。

1、JAVA 中的 String,如果有则返回,如果没有则创建一个字符串保存在字符串缓存池里面。 2、数据库的数据池。

优点: 大大减少对象的创建,降低系统的内存,使效率提高。

缺点:提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质,不应该随着内部状态的变化而变化,否则会造成系统的混乱。

使用场景: 1、系统有大量相似对象。 2、需要缓冲池的场景。

注意事项: 1、注意划分外部状态和内部状态,否则可能会引起线程安全问题。 2、这些类必须有一个工厂对象加以控制。

  • 返回改对象,没有;就创建一个新对象并且存储在hashMap中 ; 并把该对象返回客户端;

迭代器模式属于行为型模式。

  • 提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
  • 主要解决:不同的方式来遍历整个整合对象。
  • 何时使用:遍历一个聚合对象
  • 如何解决:把在元素之间游走的责任交给迭代器,而不是聚合对象。
  • 优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类迭代器类都很方便,无须修改原有代码。
  • 缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性
  • 使用场景: 1、访问一个聚合对象的内容而无须暴露它的内部表示。 2、需要为聚合对象提供多种遍历方式。 3、为遍历不同的聚合结构提供一个统一的接口。

注意事项:迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。

 包中 J2SE 的 API 包含有类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节。
 
 
.Socket 类代表一个套接字,并且 .ServerSocket 类以获取一个端口,并且侦听客户端请求。
 
创建非绑定服务器套接字。 如果 ServerSocket 构造方法没有抛出异常,就意味着你的应用程序已经成功绑定到指定的端口,并且侦听客户端请求。
 

 
java.net.Socket 类代表客户端和服务器都用来互相沟通的套接字。客户端要获取一个 Socket 对象通过实例化 ,而 服务器获得一个 Socket 对象则通过 accept() 方法的返回值。
 
当 Socket 构造方法返回,并没有简单的实例化了一个 Socket 对象,它实际上会尝试连接到指定的服务器和端口。
下面列出了一些感兴趣的方法,注意客户端和服务器端都有一个 Socket 对象,所以无论客户端还是服务端都能够调用这些方法。
 

 
这个类表示互联网协议(IP)地址。下面列出了 Socket 编程时比较有用的方法:
 

 
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
文章开始,先给大家奉上一道经典的测试题。
请问,上面代码最终结果输出的是什么?不了解泛型的和很熟悉泛型的同学应该能够答出来,而对泛型有所了解,但是了解不深入的同学可能会答错。
正确答案是 true。
上面的代码中涉及到了泛型,而输出的结果缘由是类型擦除

 
泛型的英文是 generics,generic 的意思是通用,而翻译成中文,泛应该意为广泛,型是类型。所以泛型就是能广泛适用的类型。
但泛型还有一种较为准确的说法就是为了参数化类型,或者说可以将类型当作参数传递给一个类或者是方法。
那么,如何解释类型参数化?
假设 Cache 能够存取任何类型的值,于是,我们可以这样使用它。
使用的方法也很简单,只要我们做正确的强制转换就好了。
但是,泛型却给我们带来了不一样的编程体验。
这就是泛型,它将 value 这个属性的类型也参数化了,这就是所谓的参数化类型。再看它的使用方法。
最显而易见的好处就是它不再需要对取出来的结果进行强制转换了。但,还有另外一点不同。
泛型除了可以将类型参数化外,而参数一旦确定好,如果类似不匹配,编译器就不通过。 上面代码显示,无法将一个 String 对象设置到 cache2 中,因为泛型让它只接受 Integer 的类型。
所以,综合上面信息,我们可以得到下面的结论。
  1. 与普通的 Object 代替一切类型这样简单粗暴而言,泛型使得数据的类别可以像参数一样由外部传递进来。它提供了一种扩展能力。它更符合面向抽象开发的软件编程宗旨。
  2. 当具体的类型确定后,泛型又提供了一种类型检测的机制,只有相匹配的数据才能正常的赋值,否则编译器就不通过。所以说,它是一种类型安全检测机制,一定程度上提高了软件的安全性防止出现低级的失误。
  3. 泛型提高了程序代码的可读性,不必要等到运行的时候才去强制转换,在定义或者实例化阶段,因为 Cache 这个类型显化的效果,程序员能够一目了然猜测出代码要操作的数据类型。
 
下面的文章,我们正常介绍泛型的相关知识。

 
泛型按照使用情况可以分为 3 种。
 

 
泛型类的声明和非泛型类的声明类似,除了在类名后面添加了类型参数声明部分。
和泛型方法一样,泛型类的类型参数声明部分也包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。因为他们接受一个或多个参数,这些类被称为参数化的类或参数化的类型。
我们可以这样定义一个泛型类。
尖括号<>中的 T 被称作是类型参数,用于指代任何类型。事实上,T 只是一种习惯性写法,如果你愿意。你可以这样写。
但出于规范的目的,Java 还是建议我们用单个大写字母来代表类型参数。常见的如:
  1. T 代表一般的任何类。
  2. V 代表 Value 的意思,通常与 K 一起配合使用。
  3. S 代表 Subtype 的意思,文章后面部分会讲解示意。
 
如果一个类被<T>的形式定义,那么它就被称为是泛型类。
那么对于泛型类怎么样使用?
只要在对泛型类创建实例的时候,在尖括号中赋值相应的类型便是。T 就会被替换成对应的类型,如 String 或者是 Integer。你可以相像一下,当一个泛型类被创建时,内部自动扩展成下面的代码。
当然,泛型类不至接受一个类型参数,它还可以这样接受多个类型参数。

 
你可以写一个泛型方法,该方法在调用时可以接收不同类型的参数。根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。
下面是定义泛型方法的规则:
  • 所有泛型方法声明都有一个类型参数声明部分(由尖括号分隔),该类型参数声明部分在方法返回类型之前(在下面例子中的 )。
  • 每一个类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开。一个泛型参数,也被称为一个类型变量,是用于指定一个泛型类型名称的标识符。
  • 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。
  • 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。
 
泛型方法与泛型类稍有不同的地方是,类型参数也就是尖括号那一部分是写在返回值前面的。<T> 中的 T 被称为类型参数,而方法中的 T 被称为参数化类型,它不是运行时真正的参数。
当然,声明的类型参数,其实也是可以当作返回值的类型的。

泛型类与泛型方法的共存现象

 
上面代码中,Test1<T> 是泛型类,testMethod 是泛型类中的普通方法,而 testMethod1 是一个泛型方法。而泛型类中的类型参数与泛型方法中的类型参数是没有相应的联系的,泛型方法始终以自己定义的类型参数为准。
所以,针对上面的代码,我们可以这样编写测试代码。
泛型类的实际类型参数是 String,而传递给泛型方法的类型参数是 Integer,两者不想干。
但是,为了避免混淆,如果在一个泛型类中存在泛型方法,那么两者的类型参数最好不要同名。比如,Test1<T> 代码可以更改为这样

 
泛型接口和泛型类差不多,所以一笔带过。

 
除了用 <T> 表示泛型外,还有 <?> 这种形式。 被称为通配符。
可能有同学会想,已经有了 的形式了,为什么还要引进 <?> 这样的概念呢?
上面代码显示,BaseSub 的父类,它们之间是继承关系,所以 Sub 的实例可以给一个 Base 引用赋值,那么
最后一行代码成立吗?编译会通过吗?


但是,在现实编码中,确实有这样的需求,希望泛型能够处理某一范围内的数据类型,比如某个类和它的子类,对此 Java 引入了通配符这个概念。
所以,通配符的出现是为了指定泛型中的类型范围。
通配符有 3 种形式。
  1. <?> 被称作无限定的通配符。
 

 
上面的代码中,方法内的参数是被无限定通配符修饰的 Collection 对象,它隐略地表达了一个意图或者可以说是限定,那就是 testWidlCards() 这个方法内部无需关注 Collection 中的真实类型,因为它是未知的。所以,你只能调用 Collection 中与类型无关的方法。
我们可以看到,当 <?> 存在时,Collection 对象丧失了 add() 方法的功能,编译器不通过。 我们再看代码。
有人说,<?> 提供了只读的功能,也就是它删减了增加具体类型元素的能力,只保留与具体类型无关的功能。它不管装载在这个容器内的元素是什么类型,它只关心元素的数量、容器是否为空?我想这种需求还是很常见的吧。
有同学可能会想,<?> 既然作用这么渺小,那么为什么还要引用它呢?
个人认为,提高了代码的可读性,程序员看到这段代码时,就能够迅速对此建立极简洁的印象,能够快速推断源码作者的意图。

 
<?> 代表着类型未知,但是我们的确需要对于类型的描述再精确一点,我们希望在一个范围内确定类别,比如类型 A 及 类型 A 的子类都可以。

但是,它仍然丧失了写操作的能力。也就是说

没有关系,我们不知道具体类型,但是我们至少清楚了类型的范围。

 

<? super T> 神奇的地方在于,它拥有一定程度的写操作的能力。

通配符与类型参数的区别

 
一般而言,通配符能干的事情都可以用类型参数替换。 比如


值得注意的是,如果用泛型方法来取代通配符,那么上面代码中 collection 是能够进行写操作的。只不过要进行强制转换。
需要特别注意的是,类型参数适用于参数之间的类别依赖关系,举例说明。
E 类型是 T 类型的子类,显然这种情况类型参数更适合。 有一种情况是,通配符和类型参数一起使用。
如果一个方法的返回类型依赖于参数的类型,那么通配符也无能为力。

 
泛型是 Java 1.5 版本才引进的概念,在这之前是没有泛型的概念的,但显然,泛型代码能够很好地和之前版本的代码很好地兼容。
这是因为,泛型信息只存在于代码编译阶段,在进入 JVM 之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。
通俗地讲,泛型类和普通类在 java 虚拟机内是没有什么特别的地方。回顾文章开始时的那段代码




Erasure 是一个泛型类,我们查看它在运行时的状态信息可以通过反射。



那我们可不可以说,泛型类被类型擦除后,相应的类型就被替换成 Object 类型呢?
这种说法,不完全正确。


我们现在可以下结论了,在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如<T>则会被转译成普通的 Object 类型,如果指定了上限如 <T extends String> 则类型参数就被替换成类型上限。



也就是说,如果你要在反射中找到 add 对应的 Method,你应该调用 getDeclaredMethod("add",Object.class) 否则程序会报错,提示没有这么一个方法,原因就是类型擦除的时候,T 被替换成 Object 类型了。

 
类型擦除,是泛型能够与之前的 java 版本代码兼容共存的原因。但也因为类型擦除,它会抹掉很多继承相关的特性,这是它带来的局限性。
理解类型擦除有利于我们绕过开发当中可能遇到的雷区,同样理解类型擦除也能让我们绕过泛型本身的一些限制。比如
正常情况下,因为泛型的限制,编译器不让最后一行代码编译通过,因为类似不匹配,但是,基于对类型擦除的了解,利用反射,我们可以绕过这个限制。
上面是 List 和其中的 add() 方法的源码定义。
因为 E 代表任意的类型,所以类型擦除时,add 方法其实等同于
那么,利用反射,我们绕过编译器去调用 add 方法。

可以看到,利用类型擦除的原理,用反射的手段就绕过了正常开发中编译器不允许的操作限制。
 
泛型类或者泛型方法中,不接受 8 种基本数据类型。
 
所以,你没有办法进行这样的编码。
需要使用它们对应的包装类。

有的同学可能对于连续的两个 T 感到困惑,其实 是为了说明类型参数,是声明,而后面的不带尖括号的 T 是方法的返回值类型。 你可以相像一下,如果 test() 这样被调用 test("123");

Java 不能创建具体类型的泛型数组
这句话可能难以理解,代码说明。
这两行代码是无法在编译器中编译通过的。原因还是类型擦除带来的影响。


借助于无限定通配符却可以,前面讲过 ? 代表未知类型,所以它涉及的操作都基本上与类型无关,因此 jvm 不需要针对它对类型作判断,因此它能编译通过,但是,只提供了数组中的元素因为通配符原因,它只能读,不能写。比如,上面的 v 这个局部变量,它只能进行 get() 操作,不能进行 add() 操作,这个在前面通配符的内容小节中已经讲过。

 
我们可以看到,泛型其实并没有什么神奇的地方,泛型代码能做的非泛型代码也能做。
而类型擦除,是泛型能够与之前的 java 版本代码兼容共存的原因。
可量也正因为类型擦除导致了一些隐患与局限。
但,我还是要建议大家使用泛型,如官方文档所说的,如果可以使用泛型的地方,尽量使用泛型。
毕竟它抽离了数据类型与代码逻辑,本意是提高程序代码的简洁性和可读性,并提供可能的编译时类型转换安全检测功能。
类型擦除不是泛型的全部,但是它却能很好地检测我们对于泛型这个概念的理解程度。
 
  • 表示该通配符所代表的类型是T类型的子类。
  • 表示该通配符所代表的类型是T类型的父类。
 
对于泛型,只是允许程序员在编译时检测到非法的类型而已。
但是在运行期时,其中的泛型标志会变化为 Object 类型。

VMware是一个很强大的虚拟机工具,可以在主机系统内运行安装的虚拟机系统,且互不影响。那么能不能实现本地系统与虚拟机系统之间的数据传输呢?我们可以通过将虚拟机硬盘映射本地磁盘的方法来实现文件的共享。

1、打开VMware虚拟机,右击想要映射本地磁盘的虚拟机系统(如win10x64),选择“设置(s)...”;

2、点击下面的“添加(A)...”按钮;

3、硬件类型选择“硬盘”,并点击下一步;

4、选择虚拟磁盘类型,建议选推荐的SCSI(s),点击下一步;

5、接下来“选择磁盘”,选择第3个“使用物理磁盘(适用于高级用户)(P)”,选择此项后可以提供直接访问本地硬盘的权限;

6、选择物理磁盘,“设备”中,如果你只有一块硬盘,就不用选了,如果有多块硬盘,可以进行选择,“使用情况”一栏,如果想映射所有本地磁盘(C、D、E、F...),就选择“使用整个磁盘”,如果想映射本地宿主机的某一个或多个磁盘分区,就点击“使用单个分区”;

7、进入“选择物理磁盘分区”,选择要映射到虚拟机中的分区,各个分区对应主机上的各个盘,如选择F盘(分区3),然后点击“下一步”;

8、“制定磁盘文件”,一般默认即可,点击“完成”;

9、会看到“虚拟机设置”界面多了个“新硬盘(SCSI)”,点击“确定”;

10、启动虚拟机(win10x64),在开启过程中会弹出来两个提示,点击“确定”即可;

11、进入到虚拟机系统中,打开资源管理器,可以看到本地磁盘已经映射到虚拟机中了,并且可以正常打开。

12、但是,映射到虚拟机系统中本地磁盘暂时不能在本地主机访问,只有退出虚拟机才可以正常访问。

按照上述步骤完成虚拟机磁盘的映射后就可以实现虚拟机与主机系统的文件资源共享了。

我要回帖

更多关于 虚拟机与主机共享硬盘 的文章

 

随机推荐