首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

JAVA学习day02

1、基本数据类型四类八种 2、变量定义后,不赋值,不能使用,即必须进行赋值后才能使用; 3、自增和自减++a 和a++相等但是在计算时,有如下差别a=3b=a++b=3,a=4 若a=3c=++ac=4,a=4 4、赋值 5、打印清单实现商品库存清单案例步骤:1、实现表头,是固定数据,直接写输出语句;2、表格中间,商品数据,采用变量形式,定义变量,找对数据类型,输出所有变量3、表格尾巴,一部分数据固定另一部分:商品数据进行数学计算 */ public class Shop { public static void main(String[] args) { //输出表头固定数据 System.out.println("---------商品库存清单-----------"); System.out.println("品牌型号 尺寸 价格 库存数"); //定义表格中的数据变量 //品牌型号String 尺寸,价格double 库存int String macBrand="MacBookAir"; double macSize=13.3; double macPrice=6898.88; int macCount=5; String thinkBrand="ThinkPadT450"; double thinkSize=14; double thinkPrice=5999.88; int thinkCount=10; String asusBrand="ASUS-FL5800"; double asusSize=15.6; double asusPrice=4999.5; int asusCount=18; System.out.println(macBrand+" "+macSize+" "+macPrice+" "+macCount); System.out.println(thinkBrand+" "+thinkSize+" "+thinkPrice+" "+thinkCount); System.out.println(asusBrand+" "+asusSize+" "+asusPrice+" "+asusCount); //计算库存总数,所有商品数量库存求和 int totalCount=macCount+thinkCount+asusCount; //计算所有商品的总金额,每个商品价格*库存数 double totalMoney=macCount*macPrice+thinkCount*thinkPrice+asusCount*asusPrice; System.out.println("总库存数:"+totalCount); System.out.println("所有商品的总金额:"+totalMoney); } }

优秀的个人博客,低调大师

JavaScript学习(十六)----事件处理

目录 事件与事件处理概述 事件与事件名称 JavaScript的常用事件 JavaScript的相关事件 事件处理程序的调用 1.在JavaScript中 代码: 2.在HTML中 JavaScript是基于对象(object-based)的语言,它的一个最基本的特征就是采用事件驱动(event-driven)。可以使在图形界面环境下的一切操作变得简单化。通过鼠标或热键的动作称为事件(event)。由鼠标或热键引发的一连串程序动作,称为事件驱动(event driver),而对事件进行处理的程序或函数,称为事件处理程序(event handler)。 事件与事件处理概述 事件处理是对象化编程的个很重要的环节,它可以使程序的逻辑结构更加清晰,使程序更具有灵活性,提高了程序的开发效率。事件处理的过程分为三步:①发生事件;②启动事件处理程序;③事件处理程序做出反应。其中,要使事件处理程序能够启动,必须通过指定的对象来调用相应的事件,然后通过该事件调用事件处理程序。事件处理程序可以是任意JavaScript语句,但是一般用特定的自定义函数(function) 来对事件进行处理。 事件与事件名称 事件是一些可以通过脚本响应的页面动作。当用户按下鼠标键或者提交一个表单, 甚至在页面上移动鼠标时,事件就会出现。事件处理是一段 JavaScript代码,总是与页面中的特定部分以及一定的事件相关联。当与页面特定部分关联的事件发生时,事件处理器就会被调用。 绝大多数事件的命名都是描述性的,很容易理解。例如click. submit. mousecover 等,通过名称就可以猜测其含义。但也有少数事件的名称不易理解,例如blur (英文的字面意思为“模糊”),表示一个域或者 一个表单失去焦点。通常,事件处理器的命名原则是, 在事件名称前加上前缀on.例如,对于click事件,其处理器名为onclick. JavaScript的常用事件 JavaScript的相关事件 事件 说明 鼠标键盘事件 onclick 鼠标单击时触发此事件 ondblclick 鼠标双击时触发此事件 onmousedown 按下鼠标时触发此事件 onmouseup 鼠标按下后松开鼠标时触发此事件 onmouscover 当鼠标移动到某对象范围的上方时触发此事件 onmousemove 鼠标移动时触发此事件 onmouscout 当鼠标离开某对象范围时触发此事件 onkeypress 当键盘上的某个键被按下并且释放时触发此事件 onkeydown 当键盘上某个按键被按下时触发此事件 onkeyup 当键盘上某个按键被按下后松开时触发此事件 页面相关事件 onabort 图片在下载时被用户中断时触发此事件 onbeforeunload 当前页面的内容将要被改变时触发此事件 onerror 出现错误时触发此事件 onload 页面内容完成时触发此事件(也就是页面加载事件) onresize 当浏览器的窗口大小被改变时触发此事件 onunload 当前页面将被改变时触发此事件 事件 说明 表单相关事件 onblur 当前元素失去焦点时触发此事件 onchange 当前元素失去焦点并且元素的内容发生改变时触发此事件 onfocus 当某个元素获得焦点时触发此事件 onreset 当表单中RESET的属性被激活时触发此事件 onsubmit 一个表单被递交时触发此事件 滚动字幕事件 onbounce 在Marquce内的内容移动至Marquce品示范围之外时触发此事件 onfinish 当Marquce元素完成需婴显示的内容后触发此事件当Marquce元素开始显示内容时触发此事件 onstart Marquce元素开始显示内容时触发此事件 编辑事件 onbeforecopy 当页面当前被选择内容将要复制到浏览者系统的剪贴板前触发此事件 onbeforecut 当页面中的部分或全部内容被剪切到浏览者系统剪贴板时能发此事件 onbeforeeditfocus 当前元素将要进入编辑状态时触发此事件 onbeforepaste 当要将内容从浏览者的系统剪贴板中粘贴到页面上时触发此事件 onbeforeupdate 当浏览者粘贴系统剪贴板中的内容时通知目标对象 oncontextmenu 当浏览者按下鼠标右键出现菜单时或者通过键盘的按键触发页面菜单时触发此事件 oncopy 当页面当前的被选择内容被复制后触发此事件 oncut 当页面当前的被选择内容被剪切时触发此事件 ondrag 当某个对象被拖动时触发此事件(活动事件) ondragend 当鼠标拖动结束时触发此事件,即鼠标的按钮被释放时 ondragente 当对象被鼠标拖动进入其容器范围内时触发此事件 ondragleave 当对象被鼠标拖动的对象离开其容器范围内时触发此事件 ondragover 当被拖动的对象在另一对象容器范围内拖动时触发此事件 ondragstart 当某对象将被拖动时触发此事件 ondrop 在一个拖动过程中,释放鼠标键时触发此事件 onlosecapture 当元素失去鼠标移动所形成的选择焦点时触发此事件 onpaste 当内容被粘贴时触发此事件 onselect 当文本内容被选择时触发此事件 onselectstart 当文本内容的选择将开始发生时触发此事件 事件 说明 数据绑定事件 onafterupdate 当数据完成由数据源到对象的传送时触发此事件 oncellchange 当数据来源发生变化时触发此事件 ondataavailable 当数据接收完成时触发此事件 ondatasetchanged 数据在数据源发生变化时触发此事件 ondatasetcomplete 当数据源的全部有效数据读取完毕时触发此事件 onerrorupdate 当使用onbeforeupdate事件触发取消了数据传送时,代替afterupdate事件 数据绑定事件 onrowenter 当前数据源的数据发生变化井且有新的有效数据时触发此事件 onrowexit 当前数据源的数据将要发生变化时触发此事件 onrowsdelete 当前数据记录将被删除时触发此事件 onrowsinserted 当前数据源将要插入新数据记录时触发此事件 外部事件 onafterprint 当文档被打印后触发此事件 onbeforeprint 当文档即将打印时触发此事件 onfilterchange 当某个对象的滤镜效果发生变化时触发此事件 onhelp 当浏览者按下F1键或者单击浏览器的帮助菜单时触发此事件 onpropertychange 当对象的属性之一发生变化时触发此事件 onreadystatechange 当对象的初始化属性值发生变化时触发此事件 事件处理程序的调用 在使用事件处理程序对页面进行操作时,最重要的是如何通过对象的事件来指定事件处理程序。 1.在JavaScript中 在JavaScript中调用事件处理程序,首先需要获得要处理对象的引用,然后将要执行的处理函数赋值给对应的事件。 代码: <input id="save" name="bt_save" type="button" value="保存" /> <script language="JavaScript" type="text/javascript"> var b_save=document.getElementById("save"); b_save.onclick=function(){ alert("单击了保存按钮"); } </script> 2.在HTML中 在HTML中分配事件处理程序,只需要在HTML标记中添加相应的事件,并在其中指定要执行的代码或函数名即可。 <input name="bt_save" type="button" value="保存" onclick="clickFunction();"/> <script language="JavaScript" type="text/javascript"> function clickFunction(){ alert("单击了保存按钮"); } </script>

优秀的个人博客,低调大师

JavaScript学习(十三)---RegExp对象

目录 创建RegExp对象 1.使用RegExp的显式构造函数 2.使用RegExp的隐式构造函数,采用纯文本格式 RegExp对象的属性 静态属性: index属性: input属性: lastIndex属性: lastMath属性: lastParen属性: leftContext属性: rightContext属性: $1...$9属性: 实例属性: global属性: ignoreCase属性: multiline属性: source属性: RegExp对象的方法 1.exec()方法 语法:rgExp.exec(str) rgExp: str: 例子: 2.test()方法 语法:rgexp.test(str) 例子: 创建RegExp对象 每一条正则表达式模式对应一个RegExp实例,有两种方式可以创建RegExp对象的实例。 1.使用RegExp的显式构造函数 语法:newRegExp("pattern"[,"flags"]) //即newRegExp(" 模式 "[," 标记 "]) 2.使用RegExp的隐式构造函数,采用纯文本格式 语法:/pattern/[flags] pattern部分为要使用的正则表达式模式文本,是必选项。 flags部分设置正则表达式的标志信息,是可选项。如果设置flags部分,在第一种方式中,以字符串形式存在;在第二种方式中,以文本的形式紧接在最后一个‘/’字符之后。flags可以是一下标志字符的组合。 g是全局标志。如果设置了这个标志,对某个文本执行搜索和替换操作时,将对文本中所有匹配的部分起作用。如果不设置这个标志,则仅搜索和替换最早匹配的文本内容。 i是忽略大小写标志。如果设置了这个标志,进行匹配时将忽略大小写。 m是多行标志。如果不设置这个标志,那么元字符‘^’只与整个被搜索字符串的开始位置相匹配。而元字符‘$’只与整个被搜索字符串的结束位置相匹配。 RegExp对象的属性 RegExp对象的属性分为静态属性和实例属性。 静态属性: RegExp对象的静态属性包括index、input、lastIndex、lastMath、lastParen、leftContext、rightContext以及$1...$9。 index属性: 是当前表达式模式首次匹配内容的开始位置,从0开始计数。其初始值为-1,每次匹配成功,index属性都会随之改变。 input属性: 返回当前所作用的字符串,可以简写为$_,初始值为空字符串。 lastIndex属性: 是当前表达式模式首次匹配内容中最后一个字符的下 一个位置,从0 开始计数,常被作为继续搜索时的起始位置,初始值为1,表示从起始位置开始搜索,每次成功匹配时,lastIndex属性值都会随之改变。 lastMath属性: 是当前表达式模式的最后一个匹配字符串,可以简写为$&。其初始值为空字符串("")。在每次成功匹配时,lastMatch 属性值都会随之改变。 lastParen属性: 如果表达式模式中有括起来的子匹配,是当前表达式模式中最后的子匹配所匹配到的子字符串,可以简写为$+。其初始值为空字符串("")。每次成功匹配时,lastParen 属性值都会随之改变。 leftContext属性: 是当前表达式模式最后一个匹配字符串左边的所有内容,可以简写为$’(其中'`'为键盘上Esc键下边的反单引号)。初始值为空字符串("")。每次成功匹配时,其属性值都会随之改变。 rightContext属性: 是当前表达式模式最后一个匹配字符串右边的所有内容,可以简写为$’(其中'`'为键盘上Esc键下边的反单引号)。初始值为空字符串("")。每次成功匹配时,其属性值都会随之改变。 $1...$9属性: 这些属性是只读的。如果表达式模式中有括起来的子匹配,$1..$9 属性值分别是第1~9个子匹配所捕获到的内容。如果有超过9个以上的子匹配,$1..$9属性分别对应级后的9个子匹配。在一个表达式模式中,可以指定任意多个带括号的子匹配,但RegExp对象只能存储最后的9个子匹配的结果。在RegExp实例对象的一些方法所返回的结果数组中, 可以获得所有圆括号内的子匹配结果。 实例属性: RegExp的实例有几个只读的属性,其中global表示是否为全局匹配,ignoreCase 表示是否忽略大小写,mutiline表示是否为多行匹配,source 是正则式的源文本,如“/[ab]/g"”的源文本就是“[ab]"。另外还有“ 个可写的属性是lastIndex, 表示下次执行匹配时的起始位置。下面对这几种属性进行详细说明。 global属性: 返回创建RegExp对象实例时指定的global标志(g) 的状态。如果创建RegExp对象实例时设置了g标志,该属性返回true, 否则返回false,默认值为false. ignoreCase属性: 返回创建RegExp对象实例时指定的ignoreCase标志(i)的状态。如果创建RegExp对象实例时设置了i标志,该属性返回true,否则返回false,默认值为false. multiline属性: 返回创建RegExp对象实例时指定的multiline 标志( m)的状态。如果创建RegExp对象实例时设置了m标志,该属性返回tnue,否则返回false, 默认值为false. source属性: 返回创建RegExp对象实例时指定的表达式文本字符串。 RegExp对象的方法 1.exec()方法 exec()方法用正则表达式模式在字符串中运行查找,并返回包含该查询结果的一个数组。 语法:rgExp.exec(str) rgExp: 必选项。包含正则表达式模式和可用标志的正则表达式对象。 str: 必选项。要在其中执行查找的Sring对象或字符串文字。如果exec()方法没有找到匹配,则返回null;如果找到匹配,则exec()方法返回一个数组, 并且更新全局RegExp对象的属性,以反映匹配结果。数组的0元素包含了完整的匹配,而第1~n元素中包合的是匹配中出现的任意一个子匹配。这相当于没有设置全局标志(g) 的match()方法。 如果为正则表达式设置了全局标志,exec()方法从以lastIndex的值指示的位置开始查找:如果没有设置全局标志,exec()方法忽略lastIndex的值,从字符串的起始位置开始搜索。 exec()方法返回的数组有3个属性,分别是input、index和lastIndex。input属性包含了整个被查找的字符串。index属性中包含了整个被查找字符串中匹配的子字符串的位置。lastIndex属性包含了匹配中最后一个字符串的下一个位置。 例子: <script language="JavaScript"> function RegExpTest(){ var src="I'm a good man"; //创建正则表达式模式 var re=/\w+/g; var arr; while((arr=re.exec(src))!=null) { document.write(arr.index+"-"+arr.lastIndex+arr+"\t"); } } document.write(RegExpTest()); </script> 2.test()方法 test()方法返回一个Boolean值,指出在被查找的字符串中是否存在模式。 语法:rgexp.test(str) 例子: <script language="JavaScript"> function TestDemo(re,s){ var s1; //声明变量 //检查字符串是否存在正则表达式 if(re.test(s)){ //测试是否存在 s1 = "包含"; //s包含模式 }else{ s1="不包含"; //s不包含模式 } return("'"+s+"'"+s1+"'"+re.source+"'"); } document.write(TestDemo(/boy/,"I am a good boy")); </script>

优秀的个人博客,低调大师

java8学习:ForkJoin

内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:java8实战 这篇是接上一篇并行数据处理与性能余下的问题:forkjoin进行讲解的 forkjoin的目的就是以递归的方式来拆分更小的任务,然后将每个小任务处理后的结果在合并,fork就是拆分,join就是合并 RecursiveTask 要把任务提交到这个池,就必须创建 RecursiveTask的子类,R就是你需要返回的结果类型,如果不返回结果就使用RecursiveAction类型,继承这个抽象类只需要实现一个方法 protected abstract V compute(); 此方法定以了将任务拆分成子任务的逻辑,以及无法再才分或不方便拆分时生成单个子任务结果的逻辑,(它定义了咋拆分又定义了怎么把子任务聚合) 先实现一下,再来说原理 还是实现1到一千万的累加和 public class ForkJoinImpl extends java.util.concurrent.RecursiveTask<Long> { //临界值,就是结束值减开始值的结果如果小于这个值那么就不拆分了,大于这个值才会拆分 private final int MEDIAN_NUM = 100000; //从多少计算 private int start_num = 0; //计算到多少 private int end_num = 0; //构造 public ForkJoinImpl(int start_num, int end_num) { this.start_num = start_num; this.end_num = end_num; } @Override protected Long compute() { //结束值减开始值的结果 int temp = end_num - start_num; //判断结束值减开始值的结果是否小于上面定义的临界值 if (temp <= MEDIAN_NUM){ //如果小的话,那么就不进行拆分了,就直接调用方法开始计算 return sequentiallySum(); } //到这就代表结束值减开始值的结果是大于临界值的 //继续进行拆分 //start_num到start_num + temp / 2是把数据的左半部分形成一个新的task //比如0到10,那么就是 10-0=10,temp=10,start_num=0,所以形成的新task就是(0,10/2=5),也就是左半部分 ForkJoinImpl leftTask = new ForkJoinImpl(start_num,start_num + temp / 2); //利用ForkJoinPool中的线程异步执行新创建的子任务 leftTask.fork(); //这创建的就是数据的后半段,start_num + temp / 2 = 0+10/2 = 6,所以形成的新task就是(0+10/2=6,10),也就是右半部分 ForkJoinImpl rightTask = new ForkJoinImpl(start_num + temp / 2,end_num); //同时执行第二个子任务,有可能允许进一步划分 Long rightResult = rightTask.compute(); //读取第一个子任务的结果,如果没有完成就等待 Long leftResult = leftTask.join(); //该任务的结果是两个子任务结果的组合 return rightResult + leftResult; } //计算方法:在不能进行拆分的时候进行计算 private Long sequentiallySum(){ long sum = 0; for (int i = start_num; i <= end_num; i++) { sum += i; } return sum; } } @Test public void test() throws Exception { ForkJoinImpl forkJoin = new ForkJoinImpl(0, 10000000); Long invoke = new ForkJoinPool().invoke(forkJoin); System.out.println("invoke = " + invoke); } 上面的流程的总结:当把ForkJoinImpl对象传给ForkJoinPool时,这个任务就由池中的一个线程执行,这个线程会调用任务的compute方法,该方法会检查任务是够孝道足以顺序执行,也就是我们上面定义的临界值,如果不够小就会要求再次拆分数据,并分给一个新的ForkJoinImpl,新的ForkJoinImpl也是由pool安排执行。因此这个过程是递归重复的,把缘任务拆分为更小的任务。这时候达到临街值要求后,会顺序计算每个任务的结果,然后由分支过程创建的任务二叉树遍历回到它的根。接下来会合并每个子任务的部分结果,从而得到总任务的结果。如下面的图 使用此框架的最佳做法 对一个任务嗲用join方法会阻塞调用方,直到该任务做出结果,因此有必要在两个子任务的计算都开始之后在调用它,否则,你得到的版本会比原始的顺序算法更慢更复杂,因为每个子任务都必须去等待另一个任务完成才能启动 对子任务调用fork方法可以把他排进pool,同时对左边和右边的子任务调用它似乎很自然,但这样做的效率比直接对其中一个调用compute低,这样做可以以为其中一个子任务重用同一个线程,从而避免在线程池中多分配一个任务造成的开销。比如有些写 //执行子任务 left.fork(); right.fork(); //获取子任务结果 int lResult = left.join(); int rResult = right.join(); 而更高效的写法是 leftTask.fork(); ForkJoinImpl rightTask = new ForkJoinImpl(start_num + temp / 2,end_num); //自己理解的是它一直判断是否有大于临界值,如果有就左半部分进行加入pool,而右边一直去判断是否还有大于临界值的情况 //而不至于两方都在等待,并且上面的写法需要left返回后右边才会返回。如果理解的不对请评论指正 Long rightResult = rightTask.compute(); Long leftResult = leftTask.join(); 工作窃取 对于上面会产生很多的小任务然后分配到内核上进行计算,理想情况下是所有的小任务机会全部同时执行完毕,但是由于线程是随意切换的,这种情况会发生改变:可能A已经空闲了,但是B还是忙的要死,为了解决这样的一个问题,此框架就有工作窃取的技术了 在应用中,这意味着这些任务拆不多被平均分配到pool中的所有的线程上。但每个线程都为分配给他的任务保存一个双向队列,每完成一个任务,就会从队列头上取出下一个任务开始执行,当A已经忙完,B还在忙的时候,A并不会闲下来,而是随机选一个别的线程,从队列的尾巴上偷走一个任务,这个过程一直继续下去,直到所有的任务执行完毕,所有队列都情况,这就是为什么不划分为几个大任务而是很多小任务,这样有助于更好的在工作线程之间平衡负载

优秀的个人博客,低调大师

java8学习:入门

内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。书籍购买地址:java8实战 sync的使用成本:多核CPU的每个处理器内核都有独立的告诉缓存,加锁需要这些告诉缓存同步运行,然而这有需要在内核间进行较慢的缓存一致性协议通信 流处理 流是一系列数据项,一次只生成一项。程序可以从输入流中一个个读取数据项,然后以 相同的方式将数据项写入输出流 拿Linux的管道命令来演示流过程 如上熟悉linux都清楚cat file1 file2会创建两个文件的输出流,如果加上>那么就会生成一个合并了File1和file2的新文件,cat产生的数据流会通过管道传送给tr进行内容过滤,符合条件的又会传入下一个sort方法进行排序,最后sort排序完成的结果集交给tail -3取三行,至此流算是结束了。这些的流处理行为是高效的,因为cat的数据读一条就会传给tr过滤,tr后传入sort,sort就能在cat或tr完成前先处理几行 基于上面的思想,java8引入了Stream,这样的好处是并行能力得到了极大的提升,并且站在了更高的抽象角度去编程,因为原来的编程习惯的java只能利用一个cpu,除非自己去写thread,并且thread是容易出错的 用行为参数化把代码传递给方法 java8可以通过api传递代码。 对上面的解释就是:看到上面的图的sort函数,可能它默认的只能升序或者降序排序,但是如果我们需要定制排序的话,也就只能对sort进行重新定义,那么就比如下面(java代码演示) @Test public void test() throws Exception { List<Integer> ints = Arrays.asList(1,3,4,5,1,5,7,7,8); ints.sort(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1.compareTo(o2); //升序 } }); System.out.println(ints); ints.sort(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return - o1.compareTo(o2); //降序 } }); System.out.println(ints); } 如上的代码,其实是只有renturn...是有用的,这句代码关乎到排序规则,但是其他的代码都是无用的。那么这时候就会想,只需要写一遍匿名内部类,排序逻辑根据自己需要传入不就行了。这个思想就是:通过api传递代码 并行与共享的可变数据 并发和并行的概念 并发是两个任务可以在重叠的时间段内启动,运行和完成。并行是任务在同一时间运行,例如,在多核处理器上。 并发是独立执行过程的组合,而并行是同时执行(可能相关的)计算。 并发是一次处理很多事情,并行是同时做很多事情。 应用程序可以是并发的,但不是并行的,这意味着它可以同时处理多个任务,但是没有两个任务在同一时刻执行。 应用程序可以是并行的,但不是并发的,这意味着它同时处理多核CPU中的任务的多个子任务。 一个应用程序可以即不是并行的,也不是并发的,这意味着它一次一个地处理所有任务。 应用程序可以即是并行的也是并发的,这意味着它同时在多核CPU中同时处理多个任务。 那么在以往的线程编程中,实现并行的前提就是各个副本可以独立工作,如果在多个副本出现了共享的变量或对象,这就行不通了,因为如果出现同时修改共享变量怎么办 java8的流实现比线程更容易,尽量保持流处理过程中,不访问共享的可变变量,这种函数就被称为纯函数,无副作用函数或无状态函数。但是依旧可以使用sync来实现一个可变数据,但是这样就与并行的概念相悖 函数 方法引用 编写一个目录下查询出所有隐藏文件 @Test public void test() throws Exception { File[] files = new File(".").listFiles(new FileFilter() { @Override public boolean accept(File pathname) { return pathname.isHidden(); } }); for (File file : files) { System.out.println(file); } } 如上啰里啰嗦的只是判断 pathname.isHidden(),java8引入之前只能这么写,但是现在可以这样 @Test public void test() throws Exception { File[] files = new File(".").listFiles((File::isHidden)); for (File file : files) { System.out.println("file = " + file); } } 上面是将isHidden方法做为值传入listFIles方法,与用对象引用传递对象相似,在java8里写下File::isHidden的时候,就创建了一个方法引用,然后可以传递这个引用了 lambda匿名函数 比如代码(int x ) -> x+1,代码的意思就是你传入一个2,那么他会返回3,也可以像上面定义一个方法add1,然后class::add1,但是对于简短逻辑明确的代码来说这样更简洁,如果匿名函数有很多行代码,不能一眼看出这个匿名函数是干嘛的,那么就应该把匿名函数抽出来一个方法使用 实例 bean代码 @AllArgsConstructor @NoArgsConstructor @Data public class Apple { private String color; private Integer weight; } java8之前:苹果根据条件过滤:找出绿色苹果 @Test public void test() throws Exception { List<Apple> apples = new ArrayList<>(); for (Apple apple : apples) { if ("green".equals(apple.getColor())){ System.out.println(apple); } } } java8之前:苹果根据条件过滤:找出1000克以上的大苹果 @Test public void test() throws Exception { List<Apple> apples = new ArrayList<>(); for (Apple apple : apples) { if (1000 < apple.getWeight()){ //其他代码与上面都是一直的,无奈的是只能复制黏贴改条件,复制黏贴是为限的,因为如果有一天需要改一个地方,如果忘记了另一处复制的代码,那么就会出错 System.out.println(apple); } } } java8之后 改变Apple类 @AllArgsConstructor @NoArgsConstructor @Data public class Apple { private String color; private Integer weight; public static boolean filterWeight(Apple apple){ return 1000 < apple.getWeight(); } public static boolean filterColor(Apple apple){ return "green".equals(apple.getColor()); } } 增加接口 public interface FindApple<T> { boolean find(T t); } 编写方法测试 @Test public void test() throws Exception { List<Apple> apples = new ArrayList<>(); filterApple(apples,Apple::filterColor); //java8之后:苹果根据条件过滤:找出绿色苹果 filterApple(apples,Apple::filterWeight); //java8之后:苹果根据条件过滤:找出1000克以上的大苹果 } static void filterApple(List<Apple> apples,FindApple<Apple> f){ for (Apple apple : apples) { if (f.find(apple)){ System.out.println(apple); } } } 自己实现方法引用确实有点复杂,首先要为需要过滤的类增加自实现的static方法,然后编写带有测试方法的结果,之后就是编写方法,此方法是可以接收需要测试类内static方法的。 如上方法filterApple中的f.find(apple),都是可以看出来这是在使用接口中的测试方法,但是这个方法没有实现自己的逻辑,所以到这它是不能按照要求过滤apple的,然后在上面junit测试方法中,传入的Apple::filterColor其实就是为接口中的测试方法添加逻辑,使其能按照我们的要求过滤apple 从传递方法到lambda 如上自己实现方法引用那真是脸上心里全都是mmp,为了实现方法引用,我们增加类Apple的方法,增加了接口等,如果java8要真是这样,那么宁可不用,不过java8是解决了这个问题的,他引入了lambda表达式,这时候上面的写法就可以写为 将增加的接口删掉~ 将在Apple内增加的方法删掉~ 编写代码 @Test public void test() throws Exception { List<Apple> apples = new ArrayList<>(); filterApple(apples,(apple -> "green".equals(apple.getColor()))); filterApple(apples,(apple -> (apple.getWeight() > 1000))); } static void filterApple(List<Apple> apples, Predicate<Apple> f){ for (Apple apple : apples) { if (f.test(apple)){ System.out.println(apple); } } } 这时候看到的变化是从原来的FindApple接口改变为了Predicate接口,其实这个接口的定义跟刚才的FIndApple接口内定义是一样一样的,如下 @FunctionalInterface public interface Predicate<T> { boolean test(T t); .... .... } 最大的变化就是我们并没有使用方法引用,而是直接以更直观的方法来过滤apple 流 日常写代码的时候,在java8之前如果要遍历Map中找出map对应key的特定value值,如果更加复杂的类型就需要嵌套循环并且编写出来的代码是一大坨的 void test() throws Exception {Map maps = new HashMap<>();for (Map.Entry integerStringEntry : maps.entrySet()) { if (integerStringEntry.getKey() > 1000) { if (integerStringEntry.getValue().equals("value")){ System.out.println("integerStringEntry = " + integerStringEntry); } } } } Stream api就类似SQL一样的过滤操作,如上的代码可以写为下面这样的 void test() throws Exception {Map maps = new HashMap<>();maps.entrySet().stream() .filter(entry -> entry.getKey() > 1000) .filter(entry -> entry.getValue().equals("value")) .forEach(System.out::println); } Stream 解决了经典的java程序只能利用一个cpu的问题,可以使程序并行执行,如图 - 在两个cpu上筛选数据,分割数据到两个cpu上,如1 - 按条件过滤数据,如2 - 一个cpu会将结果汇总起来,如3 Stream顺序处理 maps.entrySet().stream().... Stream的并行处理 maps.entrySet().parallelStream().... 默认方法 如上已经看到了,在java8中使用集合类都会有stream方法,那么在java8之前是没有这个方法,如果把java7升级到java8,那么多的这个stream方法不就的需要实现吗,那么不就不能向后兼容了吗? 如上的问题全是由接口内的默认方法实现的 默认方法的定义是由default开始的,比如 public interface MyFunction { default boolean test(String str) { return str.equals(".."); } } public class UU implements MyFunction{ public static void main(String[] args) { UU uu = new UU(); System.out.println(uu.test("..")); } } 如上UU类中根本不要实现接口中的test方法就可以使用,当然也可以覆盖实现 public class UU implements MyFunction{ @Override public boolean test(String str) { return "ll".equals(str); } public static void main(String[] args) { UU uu = new UU(); System.out.println(uu.test("..")); } } 这时候实现的逻辑就是子类重写之后的了 我们都知道接口是可以多重实现的,那么如果IA和IB中方法名重复了咋办 public interface MyFunction1 { default boolean test(String str) { return str.equals(".."); } } public interface MyFunction2 { default boolean test(String str) { return str.equals("ll"); } } public class UU implements MyFunction1,MyFunction2{ //exception public static void main(String[] args) { UU uu = new UU(); System.out.println(uu.test("..")); } } 如上当两个接口中的方法名重复了,那么就会出错,解决办法就是重写重复的方法即可,当然方法重载是没有问题的 这就是为什么在更新为java8之后,之前的代码还是可以使用的原因,java8 在Collection接口中加入了stream默认实现了 default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); }

优秀的个人博客,低调大师

17.Swift学习之类

类介绍 Swift虽然推荐面向协议编程,但其也是一门面向对象开发的语言 面向对象的基础是类,类产生了对象(类的实例) Swift中用class关键字定义类 定义语法 class 类名 { // 定义属性和方法 } 举例 class Person { var name = "Zhangsan" var age = 10 var sex = "man" func say(){ print("人会说话") } } 解读 定义了一个名叫 Person的类 这个类有三个变量存储属性和一个方法 类的实例 结构体一样,最简单的是在名称后面加一个(),但默认没有成员构造函数 var p1 = Person() 访问属性和方法 可以用.来访问一个实例的属性和方法 访问时如果使用了赋值语句就是设置属性 //普通构造函数 var p1 = Person() //访问 p1.age //设置 p1.age = 30 p1.name p1.sex p1.say() 类是引用类型 不同于值类型,引用类型被赋值到一个常量,变量或者本身被传递到一个函数的时候它是不会被拷贝的,而使用的是同一个对某个实例的引用。 var p2 = p1 p2.name = "Lisi" p2.age = 20 p2.sex = "woman" //对p2的修改会影响原来的p1 p1.age p1.name p1.sex 特征运算符 因为类是引用类型,可能有很多常量和变量都是引用到了同一个类的实例。有时候需要找出两个常量或者变量是否引用自同一个实例,Swift提供了两个特征运算符来检查两个常量或者变量是否引用相同的实例。 相同于 ( ===) 不同于( !==) //特征运算符 let p3 = Person() p1 === p2 //true p1 === p3 //false p1 !== p3 //true 继承 一个类可以从另一个类继承方法、属性和其他的特性 当一个类从另一个类继承的时,继承的类就是子类,被继承的就是父类 继承的目的是为了代码复用 Do Not Repeat Yourself 案例 // 定义一个父类 class Vehicle { var currentSpeed = 0.0 func makeNoise() { print("Ba Ba") } } // 定义一个子类 class Bicycle: Vehicle { var hasBasket = false } // 定义一个子类 class Car: Vehicle { var banner = "皖B12345" } var vehicle = Vehicle() vehicle.makeNoise() let bicycle = Bicycle() bicycle.makeNoise() var car = Car() car.makeNoise() 重写(覆写) 所谓重写就是子类可以对继承自父类实例方法、类型方法、实例属性,类型属性进行覆盖 重写需要在前面加上 override 关键字 override 关键字执行时Swift 编译器会检查重写的类的父类(或者父类的父类)是否有与之匹配的声明来提供重写 class Car: Vehicle { var banner = "皖B12345" override func makeNoise() { print("Di Di") } } var car = Car() car.makeNoise() 防止被重写 可以通过final标记阻止这种行为:final var , final func , final class func class Vehicle { var currentSpeed = 0.0 func makeNoise() { print("Ba Ba") } //不能被子类重写 final func run() { print("Run Run") } } 类与结构体的对比 相同点 定义属性 定义方法 定义构造函数(init函数) 可以被扩展 遵循协议 类有而结构体没有的额外功能 继承 类型转换(子类 as 父类) 析构函数 引用计数 开发中类与结构体的使用场景 类和结构体都可以用来定义自定义的数据类型,结构体实例总是通过值来传递,而类实例总是通过引用来传递。 按照通用准则,当符合以下一条或多条情形时应考虑结构体,其他情况下,使用类。大部分的自定义的数据结构应该是类,而不是结构体。 要描述的数据类型中只有少量的简单数据类型的属性 要描述的数据类型在数据传递时要以复制的方式进行 要描述的数据类型中所有的属性在进行传递时需要以复制的方式进行 不需要继承另一个数据类型 比如: 定义几何形状的大小,封装了一个 width属性和 height属性,两者为 Double类型; 定义一定范围的路径,封装了一个 start属性和 length属性,两者为 Int类型; 定义三维坐标系的一个点,封装了 x , y 和 z属性,它们是 Double类型。

优秀的个人博客,低调大师

NLP学习------HanLP使用实验

在之前的实验中得到了不在词向量里的词与分词结果,结果有500多个词不在词向量里,解决方案就是重新分词,或再追加训练这些词到词向量里。但后者相对麻烦且目前样本量不大。我跟据词向量的作者[6]所使用的分词工具来分词,会比不同工具(jieba)的效果要好,因为都是同一模式的分词,分出来的词应该都会存在于大型语料库中。实验证明思路是对的,最后结果是只有60几个词不在词向量里,其中大部分为名词,还有些为因语音翻译问题所造成的出错连词,所有这些词也只出现一次,这部分可以考虑最后删去也不会影响结果。改善未出现词是个关键步骤,因为此后模型会用到词向量,如果未出现词过多,会影响词向量效果。 问题:不过最后HANLP分词影响了实验判断结果,准确率从93%(jieba分词,同模型同参数)下降到90%。 实验:使用HanLP分词1 1,前期准备,(环境ubuntu,python3)安装JAVA-10[3](hanlp是JAVA开发的,即使使用python调用pyhanlp需要借助java),jpype(python中虚拟java环境),hanlp(开源中文处理工具,不只是分词还有各种工具),hanlp的root路径配置及data数据包放置[4] 2,主要程序[5] w2v_model = KeyedVectors.load_word2vec_format(w2vpath, binary=False, unicode_errors='ignore') # 加载词向量hanlppath="-Djava.class.path=/media/glados/Learning/project/NLP/hanlp/hanlp-1.6.4.jar:/media/glados/Learning/project/NLP/hanlp/"jp.startJVM(jp.getDefaultJVMPath(), hanlppath) # , "-Xms1g", "-Xmx1g") # 启动JVM, Xmx1g分配1g内存jp.JClass('com.hankcs.hanlp.HanLP$Config').ShowTermNature = False # 关闭分词属性显示HanLP = jp.JClass('com.hankcs.hanlp.HanLP') #普通分词模式words = str(HanLP.segment(sentence)) #分词将结果转为strwords = re.sub('[反斜杠[反斜杠],n]', ' ', words) # 这里注意实际程序是单,在blog里会出问题,所以用反斜杠替代words = words.split()words = del_stopword(words)...jp.shutdownJVM() # 最后关闭java虚拟环境 使用的是HANLP的普通分词功能,另外需注意,hanlp.segment()不能直接输出或赋值给python,因为其是java环境中数据,所以只有转为str()后,再进行处理,否则会报错#Afatalerror。(另外还有其他java与python数据对应问题,在这里没遇到,请参考其他) 词向量选用的是“Mixed-large综合”[6],其包括百度wiki百科、人民日报等,总共1293214个词。 Hanlp的中部份功能没法使用,例如精确分词CRF。另外,要先加载词向量再加载java虚拟环境。#AfatalerrorhasbeendetectedbytheJavaRuntimeEnvironment 3,实验结果 model num_topic limit F1 accuracy precision recall tflsi 3 0.45 0.888888889 0.902173913 0.9 0.87804878 (模型使用的是特征为tfidf的lsi模型, 参数:num_topics=3, 判断是否相似阀值为0.45,即大于0.45为true相似 ) 同模型同参数下,jieba分词结果 jieba分词未出现在词向量的约500多,有些词出现了好几次,而hanlp分词只有60几个未出现,且多数为名词,只出现过一次。 4,分析在样本中,所有样本分词结果jieba比hanlp要多分出100个词左右。所以推测因hanlp分词细粒度大,分出词少,导致较少的共现词出现(也可能是hanlp分词精度更高,分出很多虚词被停止词表过滤造成),也就是说,lsi+tfidf模型对词细粒度大、分词少的分词器不友好,所以最后hanlp出错率更大。 jieba与hanlp都是很不错的分词器,结巴使用更方便。hanlp准确度要高一些(感觉),而且与文中提到的词向量相匹配。 (我免贵姓AI,jieba:我免/贵姓/AI,hanlp:我/免/贵姓/AI,实际:我/免贵/姓AI)参考资料:[[自然语言处理 中文分词 词性标注 命名实体识别 依存句法分析 关键词提取 新词发现 短语提取 自动摘要 文本分类 拼音简繁]](https://github.com/hankcs/HanLP)文章来源于gladosAI的博客

优秀的个人博客,低调大师

SQL Serever学习15——进阶

特别说明:在sqlserver2014中,不区分大小写,也就是说,SQL是大小写不敏感的 数据库模型3类: 层次模型 网状模型 关系模型 关系型数据库语言3种: DDL数据定义语言 CREATE(创建书库或数据库对象) , ALTER, DROP DML数据操作语言 SELECT(检索表或视图) , UPDATE , INSERT , DELETE DCL数据控制语言 GRANT(授予权限) , REVOKE(撤销权限) , DENY(拒绝权限,并禁止从其他角色继承许可权限) 系统数据库4个: master数据库 记录所有系统信息,例如登录账户,系统配置 model数据库 所有数据库模板,对model数据库修改将应用于以后的所有数据库 msdb数据库 tempdb数据库 模板浏览器窗口 SSMS提供了大量的包含用户提供给的遍的参数的脚本模板,使用该参数可以只输入一次名称,然后自动将改名称复制到脚本中所有必要的位置。 使用模板创建数据库 将Create Database从模板浏览器窗口,拖动到查询窗口,自动创建代码 选择查询==》指定模板参数的值, 在打开的窗口中替换掉原先的值,改为“销售管理2”,确定 然后先分析,无误后,点击执行按钮即可 查看联机帮助文档 这里的帮助文档,数据量很大 选择sqlserver2014的Developer Reference ,Installation , Microsoft SQL Server Language Reference,点击更新 操作数据库的文件(增删改) 为销售管理2增加一个日志文件 先查看数据库文件 修改数据库文件 编写执行SQL,修改数据库的文件位置,大小 ALTER DATABASE 销售管理2 MODIFY FILE ( NAME=销售管理2, FILENAME='e:/data/销售管理2.mdf', SIZE=12MB ) GO 删除数据库文件 ALTER DATABASE 销售管理2 REMOVE FILE 销售管理2_2 注意:主数据库文件和主日志文件,不可删除 sqlserver2014支持的其他数据类型 数据完整性4种: 实体完整性(行,数据不重复) 域完整性(列,满足于特定约束) 参照完整性(外键约束) 用户自定义完整性(自定义的约束,触发器) 设置强制修改数据表 sqlserver2014安装的时候,默认不能强制修改数据表结构,如要修改,设置方法如下: 工具==》选项==》设计器==》表设计器和数据库设计器==》阻止保存。。。的勾选去掉,确定 创建视图的SQL(可以使用SSMS创建) CREATE VIEW 一个视图 AS SQL语句 GO 比如: USE 销售管理 GO CREATE VIEW 一个视图 AS SELECT 买家名称 FROM 买家表 GO

优秀的个人博客,低调大师

PHP学习4——面向对象

主要内容: 创建类 成员方法 构造方法 析构方法 封装 继承 接口 多态 静态成员 常用关键字 常用魔术方法 从PHP5开始引入了面向对象的全部机制,面向对象的特性符合软件工程的3个目标:重用性,灵活性,扩展性。 创建类 类前面不用public修饰,只要class,类的属性不能在初始化赋值(除非你写了构造方法来初始化赋值),属性的使用符号->,比如$aClass->name; demo.php <?php //声明ren类,默认public,不写 class ren{ public $name; public $sex; public $age; } //实例化ren类 $xiaoli=new ren(); //设置name属性 $xiaoli->name="小李"; //获取name属性 echo $xiaoli->name; ?> 输出 =》小李 成员方法 就是类中函数,只是在原先的函数声明前面加修饰符public,即可,调用方法$aClass->func(),在函数中使用该对象的属性使用关键字$this,比如$this->name; class_func.php <?php //声明ren类,默认public,不写 class ren{ public $name; public $sex; public $age; public function say(){ echo "我叫做".$this->name."<br/>"; } } //实例化ren类 $xiaoli=new ren(); //设置name属性 $xiaoli->name="小李"; //调用方法 $xiaoli->say(); ?> 输出 我叫做小李 构造方法 在类的方法中的一个特殊的方法,默认为public(不需要写),,写法:__construct(){},注意前面是2个下划线。 可以使用构造方法进行对象的初始化赋值 每一次实例化对象(new),都会执行。 construct.php <?php //声明ren类,默认public,不写 class ren{ public $name; public $sex; public $age; //成员方法 public function say(){ echo "我叫做".$this->name."<br/>"; echo "性别:".$this->sex."<br/>"; echo "年龄:".$this->age."<br/>"; } //构造方法 function __construct($name,$sex,$age){ $this->name=$name; $this->sex=$sex; $this->age=$age; } } //实例化ren类,初始化对象赋值 $xiaoli=new ren("小李","男",25); //调用方法 $xiaoli->say(); ?> 输出 我叫做小李 性别:男 年龄:25 析构方法 和构造方法名称类似,但是不能带任何参数,写法:function __destruct(){} 在销毁一个类之前执行一些操作或完成功能,在对象被销毁时自动执行。 destruct.php <?php //声明ren类,默认public,不写 class ren{ public $name; public $sex; public $age; //成员方法 public function say(){ echo "我叫做".$this->name."<br/>"; echo "性别:".$this->sex."<br/>"; echo "年龄:".$this->age."<br/>"; } //构造方法 function __construct($name,$sex,$age){ $this->name=$name; $this->sex=$sex; $this->age=$age; } //析构方法 function __destruct(){ echo "<br/>$this->name 这个对象被销毁了。<br/>"; } } //实例化ren类,初始化对象赋值 $xiaoli=new ren("小李","男",25); //调用方法 $xiaoli->say(); //对象自动销毁,执行__destruct ?> 输出 我叫做小李 性别:男 年龄:25 小李 这个对象被销毁了。 也可以使用unset方法手动销毁对象,比如$unset($xiaoli) unset.php <?php //声明ren类,默认public,不写 class ren{ public $name; public $sex; public $age; //成员方法 public function say(){ echo "我叫做".$this->name."<br/>"; echo "性别:".$this->sex."<br/>"; echo "年龄:".$this->age."<br/>"; } //构造方法 function __construct($name,$sex,$age){ $this->name=$name; $this->sex=$sex; $this->age=$age; } //析构方法 function __destruct(){ echo "<br/>$this->name 这个对象被销毁了。<br/>"; } } //实例化ren类,初始化对象赋值 $xiaoli=new ren("小李","男",25); $xiaobai=new ren("小白","女",23); //调用方法 unset($xiaoli,$xiaobai); //对象自动销毁,执行__destruct ?> 输出 小李 这个对象被销毁了。 小白 这个对象被销毁了。 封装 面向对象的3特性:封装,继承,多态 封装是面向对象的3特性之一(3特性为:封装,继承,多态) 类封装了代码,对象则封装了数据 访问关键字:public,private,protected 继承 这也是面向对象的3特性之一 继承使用的关键字为extends 继承可以拓展原先的类的属性和方法,还可以直接使用原先的类的属性和方法,节省了一大推敲代码的时间! 不过继承的是public,protected的属性和方法,至于private乃是师傅的私家珍藏(俗称“留一手”),是不会让继承的! PHP的面向对象的设计,和Java语言的设计非常的类似,难道是copy“借鉴”了Java的吗?也许吧! jicheng.php <?php //声明tool类 class tool{ function on(){ echo "<br/>启动<br/>"; } function run(){ echo "运行<br/>"; } function off(){ echo "关闭<br/>"; } } //继承tool类 class fan extends tool{ function app(){ $this->on(); $this->run(); $this->off(); } } $fan=new fan(); $fan->app(); ?> 输出 启动 运行 关闭 接口 PHP5也是单继承的,只能extends一个类,但是可以实现(相当于继承)多个接口(接口相当于是所有方法都是抽象方法,抽象类) 接口的关键字interface,实现接口implements interface.php <?php //声明接口 interface tool{ //全都是默认的public abstract 的方法 function on(); function run(); function off(); } //实现接口 class fan implements tool{ function on(){ echo "<br/>风扇启动<br/>"; } function run(){ echo "风扇运行<br/>"; } function off(){ echo "风扇关闭<br/>"; } } ?> 多态 由于PHP是弱类型语言,并不支持完全的多态。 多态就是根据不同的对象来做出不同的反应,运行同一个方法,但是得到的却是不同的结果。 duotai.php <?php //声明接口 interface tool{ //全都是默认的public abstract 的方法 function on(); function run(); function off(); } //实现接口 class fan implements tool{ function on(){ echo "<br/>风扇启动<br/>"; } function run(){ echo "风扇运行<br/>"; } function off(){ echo "风扇关闭<br/>"; } } //实现接口 class engine implements tool{ function on(){ echo "<br/>发动机启动<br/>"; } function run(){ echo "发动机运行<br/>"; } function off(){ echo "发动机关闭<br/>"; } } //状态类 class toolStatus{ function ts($tool){ $tool->on(); $tool->run(); $tool->off(); } } //应用多态 $fan=new fan(); $engine=new engine(); $toolStatus=new toolStatus(); $toolStatus->ts($fan); $toolStatus->ts($engine); ?> 输出 风扇启动 风扇运行 风扇关闭 发动机启动 发动机运行 发动机关闭 静态成员 类中一种特殊成员,不会被实例化到对象中,所以不用实例化对象即可调用。 关键字static,比如public static $name,public static function say(){}; 在类的内部使用静态的成员使用关键字self::$name,self表示类,2个冒号是作用域限定符,$name就是静态成员。 在程序中使用静态成员,写法: static.php <?php //声明tool类 class tool{ //声明静态方法 static function on(){ echo "<br/>启动<br/>"; } function run(){ //内部调用静态方法 self::on(); echo "运行<br/>"; } function off(){ echo "关闭<br/>"; } } //外部调用静态方法,不用实例化对象 tool::on(); $fan=new tool(); $fan->run(); ?> 输出 启动 启动 运行 常用关键字 final,被final(最终的)修饰的类不能被继承,修饰的属性不能被修改,比如public final function say(){} clone,建立一个对象的副本,比如$newClass=clone $aClass;他会自动调用类的__clone(){}方法 常用的魔术方法 function __construct($name,$age){}构造方法 function __destruct(){}析构方法 function __clone(){}拷贝方法 function __set($name,$value)设置方法 function__get($name)获取方法 function__call($func,$values) function static __callStatic($func,$values)

优秀的个人博客,低调大师

PHP学习5——异常处理

主要内容: PHP错误类型 异常的产生 错误日志 日志信息记录到操作系统日志 异常处理 扩展异常处理类 PHP错误类型 语法错误 执行时错误 逻辑错误 异常的产生 如果安装了xampp之后,在php.ini中可以设置错误报告,配置文件路径:C:\xampp\php 可以使用error_reporting(0)关闭错误提示,使用error_reporting(E_ALL)报告所有错误 在ini文件中使用;分号注释 错误日志 使用指定文件记录错误报告日志 在开发的产品投入使用后,通常会把所有的错误提示都关闭,因为这些提示会影响消费者对产品的体验,而且曝露太多信息容易被黑客攻击。 错误信息可以保存到单独的文本(日志文件)中而不要显示在浏览器中。 默认情况都是配置好的,在程序中可以使用error_log($msg)来自定义错误信息 error.php <?php echo "ssdsds"; error_log("这是一段自定义的报错日志信息"); ?> 打开文件 [06-Aug-2018 07:24:24 Europe/Berlin] 这是一段自定义的报错日志信息 [06-Aug-2018 07:24:50 Europe/Berlin] 这是一段自定义的报错日志信息 打开php.ini配置文件 报告PHP所有错误 设置PHP报错日志地址: 日志信息记录到操作系统日志 常用方法 openlog($msg,$option,$facility)打开日志连接,比如openlog("php",LOG_PID,LOG_USER) syslog($priority,$msg)生成日志消息,比如syslog(LOG_WARNING,"向syslog中发送自定义信息。。。") closelog()关闭日志连接 syslog.php <?php openlog("PHP5",LOG_PID,LOG_USER); syslog(LOG_WARNING,"向syslog发送自定义信息"); closelog(); ?> 自定的信息都被记录都爱系统日志中了,可以在计算机》管理》事件查看器》windows日志》应用程序》点击警告,即生成的信息。 异常处理 异常处理是一种可扩展、易维护的错误处理统一机制。 异常处理的实现 exception.php <?php try{ $error="这是异常的提示信息"; throw new Exception($error); echo "这里不会被执行"; }catch(Exception $e){ echo "错误信息:".$e->getMessage()."<br/>";; } echo "程序继续向下执行"; ?> 输出 错误信息:这是异常的提示信息 程序继续向下执行 异常必须手动抛出,关键字是throw,比如 ,throw new Exception();,注意,在异常被处理后,程序会继续向下执行。 扩展异常处理类 Exception类是所有异常的基类,可以通过继承来扩展它。 Exception.php <?php //异常类 class Exception{ protected $message='Unknow exception'; protected $code=0; protected $file; protected $line; //构造方法 public function __construct($message=null,$code=0,$previous=null){}; public function __toString();//可重载,用于返回可输出的字符串 final public function getMessage();//返回异常信息 final public function getCode();//返回异常代码 final public function getFile();//返回发生异常的文件名 final public function getLine();//返回发生异常的代码行号 final public function getTrace();//数组形式返回异常传递的线路 final public function getPrevious();//返回格式化异常 final public function getTraceAsString();//返回格式化字符串的getTrace信息 } ?> 现在我们定义自己的异常类 myException.php <?php //异常类 class cakeException extends Exception{ public function __toString(){ return "这个蛋糕过期了<br/>"; } } //异常类 class pearException extends Exception{ public function __toString(){ return "这个梨子烂了<br/>"; } } //异常类 class appleException extends Exception{ public function __toString(){ return "这个苹果坏了<br/>"; } } try{ throw new cakeException(); }catch(Exception $e){ echo $e; } try{ throw new appleException(); }catch(Exception $e){ echo $e; } try{ throw new pearException(); }catch(Exception $e){ echo $e; } ?> 输出 这个蛋糕过期了 这个苹果坏了 这个梨子烂了 上面都是直接抛出异常,在应用中,我们通过判断来抛出异常 demo.php <?php try{ $a=10; if(isset($b)){ echo "程序正常执行"; }else{ throw new Exception(); } }catch(Exception $e){ echo "错误代码所在路径:".$e->getFile()."<br/>"; echo "错误代码所在行号:".$e->getLine()."<br/>"; } echo "<br/>程序执行完毕<br/>"; ?> 输出 错误代码所在路径:C:\xampp\htdocs\demo.php 错误代码所在行号:8 程序执行完毕 ok,关于异常处理就到这里了。

优秀的个人博客,低调大师

PHP学习6——常用函数

主要内容: 字符串处理函数 时间和日期处理函数 字符串处理函数 echo输出字符串 print输出字符串,带返回值1 print.php <?php var_dump(print("有返回值的<br/>")); ?> 输出 有返回值的 int(1) die($status)输出字符串,并退出脚本 die.php <?php isset($a)|| die('$a未定义,程序退出!'); echo '$a已经定义,程序继续执行'; ?> 输出 $a未定义,程序退出! printf()格式化输出,占位符为序号+$,%表示格式化输出,d十进制,s字符串,f浮点数 printf.php <?php printf('输出第2个元素为:%2$s<br/>','this','is','apple'); //双引号中$前面+\ printf("输出第3个数为:%3\$d<br/>",10,5,20); ?> 输出 输出第2个元素为:is 输出第3个数为:20 其他方法 sprintf()将格式化字符串返回给一个变量 trim()从字符串2边删除预定义字符 htmlspecialchars()把一些预定义字符转换为html实体,这个方法很重要,在提交表单的时候,可以防止xss(cross-site scripting)跨站攻击 提示:跨站点脚本(Cross-site scripting,XSS)是一种计算机安全漏洞类型,常见于 Web 应用程序。 XSS 能够使攻击者向其他用户浏览的网页中输入客户端脚本。 htmlspecialchars() 函数把特殊字符转换为 HTML 实体。这意味着 < 和 > 之类的 HTML 字符会被替换为 &lt; 和 &gt; 。 这样可防止攻击者通过在表单中注入 HTML 或 JavaScript 代码(跨站点脚本攻击)对代码进行利用。 时间和日期处理函数 unix时间戳,表示格林威治时间,从1970年1月1日0时0分0秒起到现在的总秒数。 mktime.php <?php echo mktime(1,0,0,01,01,1970); ?> 输出:0 还有一个time(),不带任何参数,返回当前时间戳, time.php <?php echo time(); ?> 输出:1533537715 getdate()返回当前的时间信息,是返回一个数组,使用print_r()输出 getdate.php <?php print_r(getdate()); ?> 输出 Array ( [seconds] => 33 [minutes] => 45 [hours] => 8 [mday] => 6 [wday] => 1 [mon] => 8 [year] => 2018 [yday] => 217 [weekday] => Monday [month] => August [0] => 1533537933 ) date("Y-m-d H:i:s")日期的格式化输出 date.php <?php echo date("Y-m-d H:i:s"); ?> 输出 2018-08-06 08:49:23 date_default_timezone_set("PRC")设置默认时区 date_default_timezone_set.php <?php echo date("Y-m-d H:i:s"); echo "<br/>"; //设置为北京时间 date_default_timezone_set("PRC"); echo date("Y-m-d H:i:s"); ?> 输出 2018-08-06 08:53:33 2018-08-06 14:53:33 microtime(true)返回程序级别的操作时间 microtime.php <?php $a=microtime(true); for($i=0;$i<1000000;$i++){ $x=10; } $b=microtime(true); $c=($b-$a); echo $c." sec"; ?> 输出 0.021001100540161 sec

优秀的个人博客,低调大师

PHP学习2——基本语法

主要内容: 二进制 数据类型 变量 常量 赋值 语句结构 函数 网站的核心功能是展现信息,文字,图片,视频,音频,对于计算机来说都是数据,这些数据按照二进制进行存储。 二进制 就是1100,0100,1010这样的数据就是二进制数,二进制数分为有符号数、无符号数。原码,反码,补码是有符号数才有的表示方法。 对于正数:原码=反码=补码 原码:0100,0100,1010 反码:0100,0100,1010 补码:0100,0100,1010 对于负数:原码!=反码,反码+1=补码 原码:1100,0100,1010 反码:1011,1011,0101 补码:1011,1011,0110 数据类型 整数(10112),浮点数(12.34),字符串("cat"/‘cat’) 变量 使用$符号申明变量,以英文字母或者_(下划线)开头,后面可是是英文字母,数字,下划线,比如$score,$mark,$name,$Password php预定义变量: $GLOBALS(当前程序中全局变量) $SERVER(全局变量,包含头信息,脚本位置的数组) $_COOKIE(通过http的cookie方法提交到脚本的变量) $_SERVER常见的$_SERVER的元素包括: PHP_SELF(当前正在执行的脚本的文件名) SERVER_ADD(当前执行脚本所在服务器ip) DOCUMENT_ROOT(当前脚本所在文档根目录) SCRIPT_FILENAME(当前执行脚本绝对路径) demo2.php <?php $a="this is test!"; echo "通过\$GLOBALS来获取变量值:"; echo $GLOBALS['a']."<br/>"; echo "当前执行脚本的文件名:"; echo $_SERVER['PHP_SELF']."<br/>"; echo "当前执行脚本的跟目录:"; echo $_SERVER['DOCUMENT_ROOT']."<br/>"; echo "当前执行脚本的绝对路径:"; echo $_SERVER['SCRIPT_FILENAME']."<br/>"; ?> 启动xampp的控制面板,运行Apache,绿色说明是正常运行 将文件拷贝的xampp的htdocs下 打开浏览器输入:http://localhost/demo2.php 常量 const name=value; 比如:const MONEY_RATE=0.5; 常用预定义常量 __FILE__(放回当前文件名称,注意下划线是两个) __LINE__(返回当前代码所在行号,注意下划线是两个) __FUNCTION__(返回所在函数的名称,注意下划线是两个) __CLASS__(返回所在的类名,注意下划线是两个) PHP_OS(返回操作系统名称) TRUE(布尔值,真) FALSE(布尔值,假) NULL(空值) demo3.php <?php echo "当前文件所在位置:".__FILE__."<br/>"; echo "当前操作系统是:".PHP_OS; ?> 赋值 赋值最基本的运算 demo4.php <?php $a="this is test!";//申明变量,并赋值 $b; $b='this is test!';//先申明变量,后赋值 $c=$a;//使用一个变量给另一个变量赋值 ECHO $a."<br/>"; echo $b."<br/>"; echo $c."<br/>"; ?> 输出: 字符串单引号和双引号 单引号的变量做字符串处理,双引号变量会解析出来 demo5.php <?php $a="this is test!"; $b=10; echo '$a'.'<br/>'.'$b'."<br/>"; echo "$a".'<br/>'."$b"."<br/>"; ?> 输出 语句结构 PHP语句通常是表达式组成,语句;(英文分号)结尾,不加会报错。 条件构成 关系运算:>(大于),<(小于),==(等于),===(全等于,包括类型),<>或!=(不等于),!==(非全等于,左右操作数数值或者类型不相等,返回真) 逻辑运算 and/&&/&(逻辑与true&true==>true) or/||/|(逻辑或false||false==>false) not/!(逻辑非!true==>false) xor/^(逻辑异或,true^false==>true ,false^true==>true,false^false==>false) 逻辑与(&&)的短路原则: exp1&&exp2,如果exp1为false,则exp2不执行,直接返回false 分支结构 if语句 if-else语句 if-elseif-else语句 switch语句 demo6.php <?php $a=5; $b=10; if($a>$b){ echo '$a大于$b'; }else{ echo '$a小于$b'; } ?> 输出$a小于$b 循环结构 while语句 do-while语句 for语句 demo7.php <?php //for循环 for($i=0;$i<10;$i++){ echo 'good! '; } ?> 输出good! good! good! good! good! good! good! good! good! good! 函数 PHP的函数很好用,不用申明返回数据的类型(当然这是优点也是缺点,不过我认为还是优点,减少了代码量啊,有没有!而且还不用想破头到底应该返回什么类型数据,而且PHP的输出支持链式调用,太方便了啊!) 函数把一个完整的功能多条语句封装成一个模块,函数使用function来申明 demo8.php <?php //输出n次变量a function printString($a,$n){ //for循环 for($i=0;$i<$n;$i++){ echo "$a"; } } //调用函数 printString("good! ",5); printString("<br/>",2); printString("apple and pear! ",1); ?> 输出 这个时候的函数参数为值传递,就是一个copy,在函数内部改变这个值不会影响到外部的变量的值,但是如果我们想要在函数内部改变外部的值,需要引用传递,将参数的引用路径地址&a传入 demo.9.php <?php //交换$a,$b位置 function swap(&$a,&$b){ echo "交换前:".'$a='.$a.'$b='.$b; echo '<br/>'; $temp=$a; $a=$b; $b=$temp; echo "交换后:".'$a='.$a.'$b='.$b; } $a=5; $b=9; //调用 swap($a,$b) ?> 输出 交换前:$a=5$b=9 交换后:$a=9$b=5 全局变量 函数中不能直接使用全局变量,如果需要在函数中使用申明的全局变量,需要加前缀global <?php $a=100; //输出全局变量a function gbl(){ global $a; echo $a; } //调用 gbl(); ?> 输出 100 静态变量 函数外不能直接使用函数内部的变量,如果需要在函数外使用申明的函数中的变量,函数中变量需要加前缀static <?php //输出静态变量a function stc(){ static $a=0; $a++; echo $a.','; } //调用 stc(); stc(); stc(); stc(); stc(); ?> 输出 1,2,3,4,5, 返回值 PHP的函数不用声明返回值类型,真方便! <?php //返回字符型 function reutrnString(){ return "today is sunday."; } //返回数字 function returnNum(){ return 1024; } //调用 $a=reutrnString(); echo "\$a=$a"."<br/>"; $a=returnNum(); echo "\$a=$a"; ?> 输出 $a=today is sunday. $a=1024 函数引用返回 需要在申明函数的时候,在函数前面在&(取地址符号) (这个有点变态,直接操作引用地址,用起来出错了怎么搞) <?php //返回数字 function &returnNum(){ static $b=0; $b=$b+1; echo $b.'<br/>'; return $b; } //调用 $a=returnNum(); //使用& $a=&returnNum(); $a=1000; $a=returnNum(); ?> 输出 1 2 1001 可变函数 需要在调用函数的时候在前面加$(申明变量符号),调用同一个函数,但是却执行的是不一样的代码, 这个技术太牛逼!要是可以在配置文件中对变量进行修改,那么就可以动态的决定要执行那个函数,根据需求动态的修改程序,牛!!! (这个更加变态,不说了,看代码) <?php //返回字符型 function reutrnString(){ echo "today is sunday.<br/>"; } //返回数字 function returnNum(){ echo 1024; } function hello(){ echo '你好'; } //调用 $func='reutrnString'; $func(); $func='returnNum'; $func(); $func='hello'; $func(); ?> 输出 today is sunday. 1024你好 递归函数 就是函数自己调用自己,没有什么好说的,在一些算法中为了简化可能会用到,但是递归调用的代码执行效率极低,不建议使用 <?php //递归 function add(){ static $a=0; $a++; echo '$a='.$a.","; if($a>10){ return; } //调用自己,直到满足条件 add(); } add(); ?> 输出 $a=1,$a=2,$a=3,$a=4,$a=5,$a=6,$a=7,$a=8,$a=9,$a=10,$a=11, 系统函数 就是PHP将一些常用的函数封装好了,不用自己写了,看看API直接使用就行了。 <?php //返回最大值 $a=max(1,22,34,777,3,55); echo "1,22,34,777,3,55中最大的数是:".$a; ?> 输出 1,22,34,777,3,55中最大的数是:777

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册