Winform开发框架之通用Windows摄像头调用拍照--SNF快速开发平台3.3-Spring.Net.Framework
今天做了一个windows系统下调用摄像头、进行开启、关闭、拍照、设置等等功能演示。
进行源码贡献,欢迎大家下载使用
一、DEMO效果如下:
二、DEMO演示代码如下:
- using SNF.Utilities;
- using SNF.WinForm;
- /// <summary>
- /// CameraDemo.cs
- /// Windows摄像头调用DEMO
- ///
- /// 修改记录
- ///
- /// 2016.10.28 版本:1.0 WangJinDou 创建。
- ///
- /// <author>
- /// <name>王金斗</name>
- /// <date>2016.10.28</date>
- /// </author>
- /// </summary>
- public partial class CameraDemo : BaseForm
- {
- public CameraDemo()
- {
- InitializeComponent();
- }
- Camera WC;
- private void CameraDemo_Load(object sender, EventArgs e)
- {
- WC = new Camera(this.panelPreview.Handle, this.panelPreview.Width, this.panelPreview.Height);
- }
- //打开摄像头
- private void btnOpen_Click(object sender, EventArgs e)
- {
- WC.StartWebCam();
- }
- //关闭摄像头
- private void btnClose_Click(object sender, EventArgs e)
- {
- WC.CloseWebCam();
- }
- //拍照
- private void btnPicture_Click(object sender, EventArgs e)
- {
- string path = FileDialogHelper.OpenDir();
- if (!string.IsNullOrEmpty(path))
- {
- WC.GrabImage(path + "/" + DateTime.Now.ToString("yyyy-MM-dd") + ".jpg");
- }
- }
- //抓图到剪切板
- private void btnPictureClip_Click(object sender, EventArgs e)
- {
- WC.GrabImageToClipBoard();
- }
- /// <summary>
- /// 弹出视频格式设置对话框
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void btnSetCaptureFormat_Click(object sender, EventArgs e)
- {
- WC.SetCaptureFormat();
- }
- //弹出色彩设置对话框
- private void btnSetCaptureSource_Click(object sender, EventArgs e)
- {
- WC.SetCaptureSource();
- }
- }
三、具体类源码
- //-----------------------------------------------------------------
- // All Rights Reserved , Copyright (C) 2015 , Spring TECH, Ltd.
- //-----------------------------------------------------------------
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Runtime.InteropServices;
- namespace SNF.Utilities
- {
- /// <summary>
- /// Camera
- /// 摄像头操作辅助类,包括开启、关闭、抓图、设置等功能
- /// <author>
- /// <name>WangJinDou</name>
- /// <date>2014-02-05</date>
- /// </author>
- /// </summary>
- public class Camera
- {
- private IntPtr lwndC;
- private IntPtr mControlPtr;
- private int mWidth;
- private int mHeight;
- // 构造函数
- public Camera(IntPtr handle, int width, int height)
- {
- mControlPtr = handle;
- mWidth = width;
- mHeight = height;
- }
- // 帧回调的委托
- public delegate void RecievedFrameEventHandler(byte[] data);
- public event RecievedFrameEventHandler RecievedFrame;
- private AviCapture.FrameEventHandler mFrameEventHandler;
- /// <summary>
- /// 关闭摄像头
- /// </summary>
- public void CloseWebCam()
- {
- this.capDriverDisconnect(this.lwndC);
- }
- /// <summary>
- /// 开启摄像头
- /// </summary>
- public void StartWebCam()
- {
- byte[] lpszName = new byte[100];
- byte[] lpszVer = new byte[100];
- AviCapture.capGetDriverDescriptionA(1, lpszName, 100, lpszVer, 100);
- this.lwndC = AviCapture.capCreateCaptureWindowA(lpszName, AviCapture.WS_VISIBLE + AviCapture.WS_CHILD, 0, 0, mWidth, mHeight, mControlPtr, 0);
- if (this.capDriverConnect(this.lwndC, 0))
- {
- this.capPreviewRate(this.lwndC, 66);
- this.capPreview(this.lwndC, true);
- this.capOverlay(this.lwndC, true);
- AviCapture.BITMAPINFO bitmapinfo = new AviCapture.BITMAPINFO();
- bitmapinfo.bmiHeader.biSize = AviCapture.SizeOf(bitmapinfo.bmiHeader);
- bitmapinfo.bmiHeader.biWidth = this.mWidth;
- bitmapinfo.bmiHeader.biHeight = this.mHeight;
- bitmapinfo.bmiHeader.biPlanes = 1;
- bitmapinfo.bmiHeader.biBitCount = 24;
- this.capSetVideoFormat(this.lwndC, ref bitmapinfo, AviCapture.SizeOf(bitmapinfo));
- this.mFrameEventHandler = new AviCapture.FrameEventHandler(FrameCallBack);
- this.capSetCallbackOnFrame(this.lwndC, this.mFrameEventHandler);
- AviCapture.SetWindowPos(this.lwndC, 0, 0, 0, mWidth, mHeight, 6);
- }
- }
- /// <summary>
- /// 抓图到文件
- /// </summary>
- /// <param name="path"></param>
- public void GrabImage(string path)
- {
- IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
- AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_SAVEDIB, 0, hBmp.ToInt32());
- }
- /// <summary>
- /// 抓图到剪切板
- /// </summary>
- /// <returns></returns>
- public bool GrabImageToClipBoard()
- {
- return AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_EDIT_COPY, 0, 0);
- }
- /// <summary>
- /// 弹出色彩设置对话框
- /// </summary>
- public void SetCaptureSource()
- {
- AviCapture.CAPDRIVERCAPS caps = new AviCapture.CAPDRIVERCAPS();
- AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_GET_CAPS, AviCapture.SizeOf(caps), ref caps);
- if (caps.fHasDlgVideoSource)
- {
- AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_DLG_VIDEOSOURCE, 0, 0);
- }
- }
- /// <summary>
- /// 弹出视频格式设置对话框
- /// </summary>
- public void SetCaptureFormat()
- {
- AviCapture.CAPDRIVERCAPS caps = new AviCapture.CAPDRIVERCAPS();
- AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_GET_CAPS, AviCapture.SizeOf(caps), ref caps);
- if (caps.fHasDlgVideoSource)
- {
- AviCapture.SendMessage(lwndC, AviCapture.WM_CAP_DLG_VIDEOFORMAT, 0, 0);
- }
- }
- #region 以下为私有函数
- private bool capDriverConnect(IntPtr lwnd, short i)
- {
- return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_DRIVER_CONNECT, i, 0);
- }
- private bool capDriverDisconnect(IntPtr lwnd)
- {
- return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_DRIVER_DISCONNECT, 0, 0);
- }
- private bool capPreview(IntPtr lwnd, bool f)
- {
- return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_PREVIEW, f, 0);
- }
- private bool capPreviewRate(IntPtr lwnd, short wMS)
- {
- return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_PREVIEWRATE, wMS, 0);
- }
- private bool capSetCallbackOnFrame(IntPtr lwnd, AviCapture.FrameEventHandler lpProc)
- {
- return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_CALLBACK_FRAME, 0, lpProc);
- }
- private bool capSetVideoFormat(IntPtr hCapWnd, ref AviCapture.BITMAPINFO BmpFormat, int CapFormatSize)
- {
- return AviCapture.SendMessage(hCapWnd, AviCapture.WM_CAP_SET_VIDEOFORMAT, CapFormatSize, ref BmpFormat);
- }
- private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr)
- {
- AviCapture.VIDEOHDR videoHeader = new AviCapture.VIDEOHDR();
- byte[] VideoData;
- videoHeader = (AviCapture.VIDEOHDR)AviCapture.GetStructure(lpVHdr, videoHeader);
- VideoData = new byte[videoHeader.dwBytesUsed];
- AviCapture.Copy(videoHeader.lpData, VideoData);
- if (this.RecievedFrame != null)
- this.RecievedFrame(VideoData);
- }
- private bool capOverlay(IntPtr lwnd, bool f)
- {
- return AviCapture.SendMessage(lwnd, AviCapture.WM_CAP_SET_OVERLAY, f, 0);
- }
- #endregion
- }
- /// <summary>
- /// 视频辅助类
- /// </summary>
- internal class AviCapture
- {
- //通过调用acicap32.dll进行读取摄像头数据
- [DllImport("avicap32.dll")]
- public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
- [DllImport("avicap32.dll")]
- public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] lpszVer, int cbVer);
- [DllImport("User32.dll")]
- public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam);
- [DllImport("User32.dll")]
- public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam);
- [DllImport("User32.dll")]
- public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam);
- [DllImport("User32.dll")]
- public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BITMAPINFO lParam);
- [DllImport("User32.dll")]
- public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref CAPDRIVERCAPS lParam);
- [DllImport("User32.dll")]
- public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
- [DllImport("avicap32.dll")]
- public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize);
- //部分常量
- public const int WM_USER = 0x400;
- public const int WS_CHILD = 0x40000000;
- public const int WS_VISIBLE = 0x10000000;
- public const int SWP_NOMOVE = 0x2;
- public const int SWP_NOZORDER = 0x4;
- public const int WM_CAP_DRIVER_CONNECT = WM_USER + 10;
- public const int WM_CAP_DRIVER_DISCONNECT = WM_USER + 11;
- public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER + 5;
- public const int WM_CAP_SET_PREVIEW = WM_USER + 50;
- public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52;
- public const int WM_CAP_SET_VIDEOFORMAT = WM_USER + 45;
- public const int WM_CAP_SAVEDIB = WM_USER + 25;
- public const int WM_CAP_SET_OVERLAY = WM_USER + 51;
- public const int WM_CAP_GET_CAPS = WM_USER + 14;
- public const int WM_CAP_DLG_VIDEOFORMAT = WM_USER + 41;
- public const int WM_CAP_DLG_VIDEOSOURCE = WM_USER + 42;
- public const int WM_CAP_DLG_VIDEODISPLAY = WM_USER + 43;
- public const int WM_CAP_EDIT_COPY = WM_USER + 30;
- public const int WM_CAP_SET_SEQUENCE_SETUP = WM_USER + 64;
- public const int WM_CAP_GET_SEQUENCE_SETUP = WM_USER + 65;
- // 结构
- [StructLayout(LayoutKind.Sequential)]
- //VideoHdr
- public struct VIDEOHDR
- {
- [MarshalAs(UnmanagedType.I4)]
- public int lpData;
- [MarshalAs(UnmanagedType.I4)]
- public int dwBufferLength;
- [MarshalAs(UnmanagedType.I4)]
- public int dwBytesUsed;
- [MarshalAs(UnmanagedType.I4)]
- public int dwTimeCaptured;
- [MarshalAs(UnmanagedType.I4)]
- public int dwUser;
- [MarshalAs(UnmanagedType.I4)]
- public int dwFlags;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
- public int[] dwReserved;
- }
- [StructLayout(LayoutKind.Sequential)]
- //BitmapInfoHeader
- public struct BITMAPINFOHEADER
- {
- [MarshalAs(UnmanagedType.I4)]
- public Int32 biSize;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 biWidth;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 biHeight;
- [MarshalAs(UnmanagedType.I2)]
- public short biPlanes;
- [MarshalAs(UnmanagedType.I2)]
- public short biBitCount;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 biCompression;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 biSizeImage;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 biXPelsPerMeter;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 biYPelsPerMeter;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 biClrUsed;
- [MarshalAs(UnmanagedType.I4)]
- public Int32 biClrImportant;
- }
- [StructLayout(LayoutKind.Sequential)]
- //BitmapInfo
- public struct BITMAPINFO
- {
- [MarshalAs(UnmanagedType.Struct, SizeConst = 40)]
- public BITMAPINFOHEADER bmiHeader;
- [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
- public Int32[] bmiColors;
- }
- [StructLayout(LayoutKind.Sequential)]
- public struct CAPDRIVERCAPS
- {
- [MarshalAs(UnmanagedType.U2)]
- public UInt16 wDeviceIndex;
- [MarshalAs(UnmanagedType.Bool)]
- public bool fHasOverlay;
- [MarshalAs(UnmanagedType.Bool)]
- public bool fHasDlgVideoSource;
- [MarshalAs(UnmanagedType.Bool)]
- public bool fHasDlgVideoFormat;
- [MarshalAs(UnmanagedType.Bool)]
- public bool fHasDlgVideoDisplay;
- [MarshalAs(UnmanagedType.Bool)]
- public bool fCaptureInitialized;
- [MarshalAs(UnmanagedType.Bool)]
- public bool fDriverSuppliesPalettes;
- [MarshalAs(UnmanagedType.I4)]
- public int hVideoIn;
- [MarshalAs(UnmanagedType.I4)]
- public int hVideoOut;
- [MarshalAs(UnmanagedType.I4)]
- public int hVideoExtIn;
- [MarshalAs(UnmanagedType.I4)]
- public int hVideoExtOut;
- }
- public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr);
- // 公共函数
- public static object GetStructure(IntPtr ptr, ValueType structure)
- {
- return Marshal.PtrToStructure(ptr, structure.GetType());
- }
- public static object GetStructure(int ptr, ValueType structure)
- {
- return GetStructure(new IntPtr(ptr), structure);
- }
- public static void Copy(IntPtr ptr, byte[] data)
- {
- Marshal.Copy(ptr, data, 0, data.Length);
- }
- public static void Copy(int ptr, byte[] data)
- {
- Copy(new IntPtr(ptr), data);
- }
- public static int SizeOf(object structure)
- {
- return Marshal.SizeOf(structure);
- }
- }
- }
- 作者: 王春天 2015-10-28
作者Blog:http://www.cnblogs.com/spring_wang- 出处: http://www.cnblogs.com/spring_wang/p/4874584.html
如果觉得还不错,欢迎转载。
SNF快速开发平台框架的系列文章:
SNF开发平台WinForm之十-Excel导入http://www.cnblogs.com/spring_wang/p/6128604.html
SNF开发平台WinForm之九-代码生成器使用说明http://www.cnblogs.com/spring_wang/p/6128595.html
SNF开发平台WinForm之八-自动升级程序部署使用说明http://www.cnblogs.com/spring_wang/p/6128570.html
SNF开发平台WinForm之七-单据打印和使用说明http://www.cnblogs.com/spring_wang/p/6126016.html
SNF开发平台WinForm之六-上传下载组件使用http://www.cnblogs.com/spring_wang/p/6125929.html
SNF开发平台WinForm之五-高级查询使用说明-http://www.cnblogs.com/spring_wang/p/6116640.html
SNF开发平台WinForm之四-开发-主细表管理页面-http://www.cnblogs.com/spring_wang/p/6116626.html
SNF开发平台WinForm之三-开发-单表选择控件创建-http://www.cnblogs.com/spring_wang/p/6116592.html
SNF开发平台WinForm之二-开发-单表表单管理页面-http://www.cnblogs.com/spring_wang/p/6116572.html
SNF开发平台WinForm之一-开发-单表表格编辑管理页面-http://www.cnblogs.com/spring_wang/p/6116523.html
Winform开发框架之通用高级查询模块--SNF快速开发平台3.3-Spring.Net.Framework
Winform开发框架之图表报表在线设计器2-图表-SNF.EasyQuery项目--SNF快速开发平台3.3-Spring.Net.Framework
Winform开发框架之图表报表在线设计器-报表-SNF.EasyQuery项目--SNF快速开发平台3.3-Spring.Net.Framework(
Winform开发框架之通用附件管理模块 --SNF快速开发平台3.3-Spring.Net.Framework
SNFAutoupdater通用自动升级组件V2.0-WinForm
SNF快速开发平台3.2之--.Net可扩展的单据编号生成器-SNF.CodeRule
SNF快速开发平台3.1之--审核流(3)低调奢华,简单不凡,实例演示-SNF.WorkFlow
SNF快速开发平台3.1之--审核流(2)流程设计-SNF.WorkFlow功能使用说明
SNF快速开发平台3.1之--审核流(1)SNF.WorkFlow审核流简介
SNF快速开发平台3.0之--完美的代码生成器SNF.CodeGenerator-快速开发者的利器
基于MVC4+EasyUI的Web开发框架--Spring.Net.FrameworkV3.0总体介绍
SNF快速开发平台3.0之--文件批量上传-统一附件管理器-在线预览文件(有互联网和没有两种)
SNF快速开发平台3.0之--asp.net mvc4 强大的导出和不需要上传文件的批量导入EXCEL
SNF快速开发平台3.0之MVC通用控件库展示-Asp.net+MVC4.0+WebAPI+EasyUI+Knockout
SNF快速开发平台3.0之BS页面展示和九大优点-部分页面显示效果-Asp.net+MVC4.0+WebAPI+EasyUI +Knockout
SNF快速开发平台3.0之-界面个性化配置+10种皮肤+7种菜单-Asp.net+MVC4.0+WebAPI+EasyUI+Knockout
SNF快速开发平台3.0之-CS页面-Asp.net+Spring.Net.Framework
SNF快速开发平台3.0之--系统里广播的作用--迅速及时、简明扼要的把信息发送给接收者
Winform开发框架之通用Windows摄像头调用拍照--SNF快速开发平台3.3-Spring.Net.Framework的更多相关文章
- SNF开发平台WinForm之十四-站内发送系统信息-SNF快速开发平台3.3-Spring.Net.Framework
1运行效果: 2开发实现: .组装站内信息发送实体对象. SNFService SNFService = new SNFService(); if (this.ucUser.SelectedIds ! ...
- SNF开发平台WinForm之十二-发送手机短信功能调用-金笛-SNF快速开发平台3.3-Spring.Net.Framework
1.调用前组装参数 2.调用发送信息服务脚本 .调用前组装参数: BaseSendTaskEntity entity = new BaseSendTaskEntity(); entity.Mess ...
- SNF开发平台WinForm之十三-单独从服务器上获取PDF文件进行显示-SNF快速开发平台3.3-Spring.Net.Framework
1运行效果: 2开发实现: 如果需要单独显示PDF文件时用下面代码去实现,指定url地址. 地址: . 获取附件管理的实体对象: List<KeyValuePair<string, obj ...
- SNF开发平台WinForm之十一-程序打包-SNF快速开发平台3.3-Spring.Net.Framework
原来我们用的是微软自带的打包工具去打包,但感觉好像也是第三方做的打包并且很是麻烦,还有时不成功报错.那综合考虑就找一个简单实用的打包工具吧,就找到了NSIS这个.具体打包步骤如下: 1.安装NSIS ...
- SNF开发平台WinForm之十-Excel导入-SNF快速开发平台3.3-Spring.Net.Framework
7.1运行效果: 2.Excel导入开发实现 2.1. 创建窗体,修改命名空间 新增的窗体命名“FrmImport表名”,这个导入窗口比较其它窗口会特殊一些,需要继承BaseFormImport父级窗 ...
- SNF开发平台WinForm之九-代码生成器使用说明-SNF快速开发平台3.3-Spring.Net.Framework
下面就具体的使用说明: 1.获取代码生成器的授权码(根据本机)-----还原数据库-------改config-----代码生成器 改代码生成器Config 2.登录代码生成器 3.查看是否连接成功 ...
- SNF开发平台WinForm之八-自动升级程序部署使用说明-SNF快速开发平台3.3-Spring.Net.Framework
9.1运行效果: 9.2开发实现: 1.首先配置服务器端,把“SNFAutoUpdate2.0\服务器端部署“目录按网站程序进行发布到IIS服务器上. 2.粘贴语句,生成程序 需要调用的应用程序的Lo ...
- SNF开发平台WinForm之七-单据打印和使用说明-SNF快速开发平台3.3-Spring.Net.Framework
8.1运行效果: 8.2开发实现: 1. 先要创建.grf报表模版,指定数据列.存储位置:Reports\Template文件夹下 2. 之后在程序当中查出数据,之后把数据和打印模版 传入方法进行 ...
- SNF开发平台WinForm之六-上传下载组件使用-SNF快速开发平台3.3-Spring.Net.Framework
6.1运行效果: 6.2开发实现: 1.先在要使用的项目进行引用,SNF.WinForm.Attachments.dll文件. 2.在工具箱内新建选项卡->选择项,浏览找到文件SNF.WinFo ...
随机推荐
- C#对Windows文件/文件夹/目录的一些操作总结
1. 在一个目录下创建一个文件夹 if (!System.IO.Directory.Exists(path)) System.IO.Directory.CreateDirectory(path); ...
- NDK 开发实例一(Android.mk环境配置下)
在我写这篇文章的时候,Android Studio已经是2.3版本了,已经集成CMake 编译工具, 用户只需在 新建项目的时候,添加选项(Include C++ support),Andr ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- 005 Spark快速入门的简单程序案例
参考:官网的quick start http://spark.apache.org/docs/1.6.0/quick-start.html 这里只是在shell命令行中简单的书写一些命令,做一个简单的 ...
- xpath-helper: 谷歌浏览器安装xpath helper 插件
1.下载文件xpath-helper.crx xpath链接:https://pan.baidu.com/s/1dFgzBSd 密码:zwvb,感谢这位网友,我从这拿到了 2.在Google浏览器里边 ...
- Java 之递归遍历目录
Java 之递归遍历目录 一.内容 输出指定目录(文件夹)下的所有文件(包括目录)的绝对路径 二.源代码:RecursiveListDirectory.java package cn.com.zfc. ...
- 潭州课堂25班:Ph201805201 爬虫基础 第八课 selenium (课堂笔记)
Selenium笔记(1)安装和简单使用 简介 Selenium是一个用于Web应用程序测试的工具. Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE(7, 8, ...
- swoole深入学习 4. process
swoole-1.7.2增加了一个进程管理模块,用来替代PHP的pcntl扩展.pcntl是php新增的一个多进程扩展,用来实现多进程,但是有很多不完善的地方,swoole 就完善了这些地方,而且使得 ...
- 面向对象&网络编程
1 接口与归一化设计 1.1 归一化概念: 归一化的好处: 1.归一化让使用者无需关心对象的类是什么,只需要知道这些对象都具备某些功能就可以了,这极大降低了使用者的使用难度. 2.归一化使得高层的外部 ...
- Java程序员面试中的多线程问题1
转自:http://blog.jobbole.com/18571/ 很多核心Java面试题来源于多线程(Multi-Threading)和集合框架(Collections Framework), 理解 ...