首页 文章 精选 留言 我的

精选列表

搜索[基础搭建],共10000篇文章
优秀的个人博客,低调大师

JavaScript 基础--- (经典案例)

案例一:全选练习 ** 使用复选框上面一个属性判断是否选中 - checked属性 - checked=true:选中 - checked=false:不选中 * 创建一个页面 ** 复选框和按钮 - 四个复选框表示爱好 - 还有一个复选框操作 全选和选不选,也有一个事件 ** 三个按钮,分别有事件 - 全选 - 全不选 - 反选 * 全选操作 步骤: /* 1、获取要操作的复选框 - 使用getElementsByName() 2、返回是数组, - 属性 checked判断复选框是否选中 *** checked = true; //表示选中 *** checked = false;//表示不选中 - 遍历数组,得到的是每一个checkbox * 把每一个checkbox属性checked=true */ * 全不选操作 步骤 /* 1、获取到要操作的复选框 2、返回的是数组,遍历数组 3、得到每一个复选框 4、设置复选框的属性 checked=false */ * 反选操作 步骤 /* 1、获取到要操作的复选框 2、返回数组,遍历数组 3、得到每一个复选框 4、判断当前的复选框是选中还是不选中 - if(love1.checked == true) {} 5、如果选中,属性checked设置成false,否则,设置成true */ * 使用复选框实现全选和全不选 步骤 /* 1、得到上面那个复选框 - 通过id获取到 2、判断这个复选框是否是选中 - if条件,checked==true 3、如果是选中,下面是全选 4、如果不是选中,下面是全不选 */ <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> table{ border: 1px solid #000; width: 400px; } </style> <script type="text/javascript"> function change(){ var all = document.getElementById("checkbox_all"); var cb = document.getElementsByName("personid"); //判断全选按钮是否被选中 if(all.checked){ for(var i = 0; i < cb.length; i++){ cb[i].checked = true; } }else{ for(var i = 0; i < cb.length; i++){ cb[i].checked = false; } } } //反选 function reverse(){ //获取所有的checkbox var cb = document.getElementsByName("personid"); for(var i = 0; i < cb.length; i++){ if(cb[i].checked){ cb[i].checked = false; }else{ cb[i].checked = true; } } } </script> </head> <body> <table border="1" cellspacing="0" cellpadding="0"> <tr> <th>全选<input type="checkbox" id="checkbox_all" onclick="change()"/></th> <th>姓名</th> <th>年龄</th> <th>手机号</th> </tr> <tr> <td><input type="checkbox" name="personid" /></td> <td>张三</td> <td>20</td> <td>15033444455</td> </tr> <tr> <td><input type="checkbox" name="personid"/></td> <td>李四</td> <td>30</td> <td>15033444456</td> </tr> <tr> <td><input type="checkbox" name="personid"/></td> <td>王五</td> <td>40</td> <td>15033444457</td> </tr> <tr> <td><input type="checkbox" name="personid"/></td> <td>赵六</td> <td>50</td> <td>15033444458</td> </tr> </table> <input type="button" value="反选" onclick="reverse()"/> </body> </html> 输出: 案例二:下拉列表左右选择 * 下拉选择框 <select> <option>111</option> <option>111</option> </select> * 创建一个页面 ** 两个下拉选择框 - 设置属性 multiple属性 ** 四个按钮,有事件 * 选中添加到右边 步骤 /* 1、获取select1里面的option - getElementsByTagName()返回是数组 - 遍历数组,得到每一个option 2、判断option是否被选中 - 属性 selected,判断是否被选中 ** selected= true: 选中 ** selected= false:没有选择 3、如果是选中,把选择的添加到右边去 4、得到select2 4、添加选择的部分 - appendChild方法 */ * 全部添加到右边 步骤 /* 1、获取第一个select下面的option对象 2、返回数组,遍历数组 3、得到每一个option对象 4、得到select2 5、添加到select2下面 - appendChild方法 */ * 选中添加到左边 步骤 /* 1、获取select2里面的option对象 2、返回是数组,遍历数组 3、得到每一个option对象 4、判断option是否被选中 - if条件 属性 selected == true:选择 5、获取select1 6、添加到select1里面 - 使用appendChild方法 */ * 全部添加到左边 步骤 /* 1、获取select2里面的option对象 2、返回是数组,遍历数组 3、得到每一个option对象 4、获取到select1 5、添加到select1里面 - 使用appendChild方法 */ <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .center{ float:left; margin-left: 100px ; } </style> </head> <body> <div class="center"> <select id="select1" multiple style="width:100px;height: 200px;" ondblclick="sel()"> <option value="选项1">选项1</option> <option value="选项2">选项2</option> <option value="选项3">选项3</option> <option value="选项4">选项4</option> <option value="选项5">选项5</option> </select> <input type="button" onclick="sel()" value="将左边选中的选项添加到右边" /> </div> <div class="center"> <select id="select2" multiple style="width:100px;height: 200px;" ondblclick="cancel_sel()"> </select> <input type="button" onclick="cancel_sel()" value="将右边选中的选项添加到左边" /> </div> </body> <script type="text/javascript"> function sel(){ var select1 = document.getElementById("select1"); var select2 = document.getElementById("select2"); var select1_options = select1.getElementsByTagName("option"); for(var i = 0; i < select1_options.length; i++){ var opt = select1_options[i]; if(opt.selected){ select2.appendChild(opt); } } } //取消选中 function cancel_sel(){ var select1 = document.getElementById("select1"); var select2 = document.getElementById("select2"); var select2_options = select2.getElementsByTagName("option"); for(var i = 0; i < select2_options.length; i++){ var opt = select2_options[i]; if(opt.selected){ select1.appendChild(opt); } } } </script> </html> 输出: 案例三:省市联动 * 创建一个页面,有两个下拉选择框 * 在第一个下拉框里面有一个事件 :改变事件 onchange事件 - 方法add1(this.value);表示当前改变的option里面的value值 * 创建一个二维数组,存储数据 * 每个数组中第一个元素是国家名称,后面的元素是国家里面的城市 * /* 1、遍历二维数组 2、得到也是一个数组(国家对应关系) 3、拿到数组中的第一个值和传递过来的值做比较 4、如果相同,获取到第一个值后面的元素 5、得到city的select 6、添加过去(使用)appendChild方法 - 创建option(三步) */ /* 由于每次都要向city里面添加option 第二次添加,会追加。 * 每次添加之前,判断一下city里面是否有option,如果有,删除 */ 方法一: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> select{ width:100px; } </style> </head> <body> 省: <select id="sheng" onchange="selectShi()"> <option value="">请选择省份</option> <option value="0">河北省</option> <option value="1">山东省</option> <option value="2">河南省</option> <option value="3">山西省</option> </select> 市: <select id="shi"> <option value="">请选择市</option> </select> </body> <script type="text/javascript"> var arrs = []; arrs[0] = ["秦皇岛","保定","石家庄","唐山"]; arrs[1] = ["济南","临沂","青岛","威海"]; arrs[2] = ["洛阳","郑州","开封","周口"]; arrs[3] = ["太原","大同","运城","忻州"]; function selectShi(){ var sheng = document.getElementById('sheng').value; var shi = document.getElementById("shi"); var shis = arrs[sheng]; //清空原来的信息 //获取市的option属性 var shi_opts = shi.getElementsByTagName("option"); //遍历删除市中的option for(var i= shi_opts.length - 1; i >= 1; i--){ var shi_opt = shi_opts[i]; shi.removeChild(shi_opt); } for(var i = 0; i < shis.length; i++){ var textNode = document.createTextNode(shis[i]); var opt = document.createElement("option"); opt.appendChild(textNode); shi.appendChild(opt); } } </script> </html> 方法二: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> select{ width:100px; } </style> </head> <body> 省: <select id="sheng" onchange="selectShi()"> <option value="">请选择省份</option> <option value="0">河北省</option> <option value="1">山东省</option> <option value="2">河南省</option> <option value="3">山西省</option> </select> 市: <select id="shi"> <option value="">请选择市</option> </select> </body> <script type="text/javascript"> var arrs = []; arrs[0] = ["秦皇岛","保定","石家庄","唐山"]; arrs[1] = ["济南","临沂","青岛","威海"]; arrs[2] = ["洛阳","郑州","开封","周口"]; arrs[3] = ["太原","大同","运城","忻州"]; function selectShi(){ var sheng = document.getElementById('sheng').value; var shi = document.getElementById("shi"); var shis = arrs[sheng]; var str = "<option value=''>请选择市</option>"; for(var i = 0; i < shis.length; i++){ str += "<option value=''>"+ shis[i] +"</option>"; } shi.innerHTML = str; } </script> </html> 输出:

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

Java 基础 之 for 循环

http://www.verejava.com/?id=16992632674123 /** for 循环 定义 : for(初始化变量;判断条件;更新循环变量){} 执行过程: 1. 初始化变量 2. 执行判断条件, 如果true 继续执行,执行完后, 更新循环变量, 再判断条件, 直到 判断条件为 false 退出循环 */ public class ForStatement { public static void main(String[] args) { //打印出0-9 /* 执行过程: 1. 初始化i=0; 2. 执行 i<10 如果为true 执行 System.out.println(i); 执行完后 i++ 再跟 i<10 判断 以此循环直到 i>=10 退出循环 */ for (int i = 0; i < 10; i++) { System.out.println(i); } } } /* while, do while, for 循环的比较 1. while 循环是先判断再循环, do while 是先执行再判断 2. for 循环一般用于下标值访问的情况 问题: 如果我们要在循环的时候中途终止,或退出需要用到 break ,continue */ http://www.verejava.com/?id=16992632674123

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

Java 基础 之 常量

http://www.verejava.com/?id=16992564786810 /* java中常量分为以下几种 1. 整型常量 2. 浮点数常量 3. 字符常量 4. 布尔型常量 5. 字符串常量 */ public class FinalVariable { public static void main(String[] args) { //常量的定义:不可以改变的变量 //1. 整型常量 final int UP=0; final int DOWN=1; final int LEFT=2; final int RIGHT=3; System.out.println(UP); System.out.println(DOWN); System.out.println(LEFT); System.out.println(RIGHT); /* 注意: 1. 常量的定义一般用大写 */ //2. 浮点数常量 final float PI=3.14f; System.out.println(PI); //3. 布尔常量 final boolean RUN=true; System.out.println(RUN); //4. 字符常量 final char A='A'; System.out.println(A); System.out.println('\r'); System.out.println('\''); System.out.println('\"'); System.out.println('\\'); //5. 字符串常量 final String CONST="情意地久天长"; System.out.println(CONST); } } /* 总结: 1. 常量的命名规则跟变量一样 2. 常量一般大写 3. 常量前面加 final 关键字 4. 常量不能改变值 */ http://www.verejava.com/?id=16992564786810

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

Java 基础 之 变量

http://www.verejava.com/?id=1699255231918 /* 注意: 1. 变量命名不允许重复 2. 变量的命名规则: 以字符,下划线,$ ,数字组成,并且开始首字母必须为 字符,下滑线或$ 不能是数字 */ public class TestVariable { public static void main(String[] args) { //变量的定义: 系统分配的一块内存区用来存储数据的地方 //String 存储数据的类型 字符串 : 以双引号" " 括起来的字符或汉字等 //bottle 变量名 //等号 = 代表赋值 也就是说将 "矿泉水" 数据存储到 名称为 bottle的内存区域中 String bottle="矿泉水"; //将变量名为bottle内存区域的数据打印输出到控制台上 System.out.println(bottle); //修改变量的值, 将 "果汁" 替换了bottle内存区域的值 bottle="果汁"; System.out.println(bottle); //清空变量, 清空bottle的内存数据 bottle=""; System.out.println(bottle); //删除变量, 赋值给null值删除变量, 这个时候垃圾回收器 GC 如果扫描到 //bottle 变量会自动回收分配的内存空间 bottle=null; System.out.println(bottle); //注意: //1.变量名是不能重复定义的, 否则编译不能通过 //String bottle="牛奶"; //System.out.println(bottle); //变量的命名规则: 以字符,下划线,$ ,数字组成,并且开始首字母必须为 字符,下滑线或$ 不能是数字 //String 1a="a"; //System.out.println(1a); String $b="b"; System.out.println($b); String _c="c"; System.out.println(_c); } } http://www.verejava.com/?id=1699255231918

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

python网络编程基础

目录 1、udp 2、tcp 3、socket函数 4、粘包问题 标签(空格分隔): 网络编程 目录 tcp和udp 1、udp tcp、udp是第四层传输层拥有的协议,用于在完成寻址功能后的数据传输。传输层将路由交换层和应用数据层划分开,主要提供数据传输控制。 udp的使用是面向无连接的,即协议自身的设计是不保证数据的有序性和重传的,这样的缺点是丢包率增加,并且无法有序的接收数据。不过这两个缺点都可以通过应用层来弥补。而udp的优点是报头小、数据传输效率高(不需要确认、协商各种流控制等等),所以udp更适用于数据需要快速传输,并对数据完整性并不太高的场景。比如:视频直播,要求实时传输,而且可以接受部分的丢帧。 udp报头非常的简单,核心只有端口+校验和 2、tcp tcp的使用是面向连接的,即数据的传输必须基于虚链路的完整建立。虚链路的建立提供了很多优秀的功能,比如确认重传以保证数据的完整性,滑动窗口以保证数据传输的高效性,各类选项字段提供不同的可选功能。tcp的缺点是报头大,因为需要包含比udp更多的功能字段,而且tcp数据的每次发送都必须得到确认否则将会重传。tcp一般应用于对数据完整性要求很高的场景。比如:ssh。 tcp的报头字段比较多,核心有:seq和ack用于处理确认重传、SYN/FIN/RST等用于提供数据包身份标记、窗口用于处理流量控制、还有各种选项。 3、socket函数 为了将路由交换和应用层分离开,socket提供了一个统一的接口供应用层直接调用而无需考虑底层路由交换的通信问题。 所有的操作系统都提供socket调用,python的socket模块也是对底层socket模块的封装,并提供了方便使用的一些函数接口。 1、建立对象 # 实例化一个socket对象,用于处理本地的socket事务,不论是服务器还是客户端都一样 # socket模块提供了很多不同类型的socket,这里选择tcp,使用ipv4 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 2、bind # socket对象可以绑定本地的ip和端口号,这个函数在服务器和客户端均可使用,不过一般不会绑定客户端 # 客户端的ip和端口一般使用随机。 # 服务器一般会固定ip和端口以供大量客户端连接 # 服务器提供的ip会通过dns发布域名 # bind的参数是一个ip+port的元组,如果没有提供ip,则会监听本机所有对外接口ip sock.bind(('127.0.0.1', 8080)) 3、listen # 此函数只应该用于服务器,因为服务器才需要监听端口等待客户主动连接 # 此函数将会告知操作系统监听socket连接 # 此函数的底层操作应该就是完成tcp三次握手 # 此函数的5表示已经完成三次握手的客户端最大数量,但是这些客户端还未与服务器交互数据 sock.listen(5) 4、connect # 此函数只应该用于客户端,因为客户端才需要连接服务器的端口 # 此函数一旦启动,则会在客户端上随机选取本地端口 # 此函数的语义是发起tcp三次握手 sock.connect(('127.0.0.1', 8080)) 5、accept # 此函数应该用于服务器,当tcp三次握手完成之后,服务器通过此函数获取此客户端socket对象和地址。 # 此函数是一个阻塞函数,即,如果服务器没有任何虚链路完成,将会无限阻塞,直到有一个虚链路通过 # listen完成,accept才会返回。 # 如果要服务器提供无限接收客户端的功能,应该循环此函数以提供链路循环 conn, addr = sock.accept() 6、recv # 此函数用于从一个socket对象(管道)中获取数据,而实际上,是从操作系统的网卡缓存中获取数据 # 可以指定需要一次获取的字节数,获取得到的数据是bytes类型,需要decode才方便阅读 # 此函数是一个阻塞函数,即,如果网卡缓存没有任何数据,则会一直阻塞到数据到达为止 msg = conn.recv() 7、send # 此函数用于将bytes类型的数据发送给socket对象(管道),而实际上,是发送给网卡缓存,后续交由 # 操作系统真正的发送数据。 # 此函数非阻塞,可以直接返回,不过要特别注意的是,msg如果为空,此函数可以正确执行,但是实际上 # 操作系统是没有发送数据给对端的。这样会产生一些socket连接的问题,所以要杜绝发空。 conn.send(msg) 8、close # 关闭虚链路 conn.close() 9、getpeername # 获取一个虚链路对端的地址二元组 print(sock.getpeername()) 4、粘包问题 根本原因:tcp面向流,无法区分消息之间的数据边界,固定recv就会导致消息粘包 解决思路:每次recv的时候动态获取,并准确的获取一个消息的长度 解决办法:每一个消息都增加固定长度的报头。每次recv的时候先获取固定长度的报头,从报头中获取本次消息的准确长度,然后再recv完整准确的信息。

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

JavaScript 基础---( window 总结)

window 概念:1.表示浏览器窗口 2.所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员 3.全局变量是 window 对象的属性 4.全局函数是 window 对象的方法 一、方法: 实例1(新建窗口) 运行: 实例2 (更改窗口大小) 实例3(移动窗口)(700,500 是 x 轴 和 Y 轴) 实例4 关闭窗口(点击关闭) 二、windom screen(获取浏览器的宽度和高度) 实例 三、windom location (浏览器地址栏) 实例 四、window History (记录访问该站点的所有页面地址) 实例 其中,history.go(0) 代表当前页面,history.go(-2)代表当前回到之前的之前页面(即后退 2 次)

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

JavaScript基础(五)数组

数组 数组定义 通过字面量定义数组: var arr = [10,20,30]; 通过构造函数定义数组: var arr = new Array(参数); // 参数位置为一个数值时为数组长度,多个数值时为数组中的元素。如果没有参数的时候 Array后面的括号可以省略。 数组操作 数组长度: 数组名.length; 数组中存储的数据类型一定是一样的吗? 类型可以不一样。 数组的长度是不是可以改变呢? 可以改变。 数组高级API 1、判断数组和转换数组 instanceof // 是一个关键字,判断A是否是B类型。 isArray() //HTML5中新增 ,判断是不是数组 toString() //把数组转换成字符串,每一项用,分割 valueOf() //返回数组对象本身 join(变量) //根据每个字符把数组元素连起来变成字符串变量可以有可以没有。不写默认用逗号分隔,无缝连接用空字符串。 instanceof var str1 = new String("abc"); var str2 = "abc"; console.log(str1 instanceof String); // true console.log(str2 instanceof String); // false join //join是把数组元素用特殊方式链接成字符串(参数决定用什么链接,无参默认用逗号链接) var arr = ["关羽","张飞","刘备"]; var str1 = arr.join(); var str2 = arr.join(" ");//如果用空格的话,那么元素之间会有一个空格 var str3 = arr.join("");//用空字符串,链接元素,无缝连接 var str4 = arr.join("&"); console.log(str1); console.log(str2); console.log(str3); console.log(str4); arguements 只在函数中使用,代表传入实参的数组。 arguements 是伪数组:不能修改长短的数组。(可以修改元素,但是不能变长变短) fn(1,2); fn(1,2,3); fn(1,2,3,4,5); function fn(a,b){ //只在函数中使用,实参的数组。 arguments[0] = 0; // 可以修改内容 console.log(arguments); //伪数组:不能修改长短的数组。(可以修改元素,但是不能变长变短) arguments.push(1); console.log(arguments instanceof Array); // false //形参个数 console.log(fn.length); //实参个数 console.log(arguments.length); // 形参和实参个数可以不同,因为实参传入的时候可以形参的个数不一样。 // arguments.callee相当于函数名,这里打印整个函数。 console.log(arguments.callee); } 2、数组增删和换位置(原数组讲被修改) push() //在数组最后面插入项,返回数组的长度 //数组1改后的长度 = 数组1.push(元素1); pop() //取出数组中的最后一项,返回最后一项 //被删除的元素 = 数组1.pop(); unshift() //在数组最前面插入项,返回数组的长度 //数组1改后的长度 = 数组1.unshift(元素1); shift() //取出数组中的第一个元素,返回最后一项 //被删除的元素 = 数组1.shift(); reverse() //翻转数组(原数组讲呗反转,返回值也是被反转后的数组) //反转后的数组 = 数组1.reverse(); sort(); //给数组排序,返回排序后的数组。如何排序看参数。 //从小到大排序后的数组 = 数组1.sort(function(a,b){ // return a-b; //}); sort var arr2 = [7,6,15,4,13,2,1]; console.log(arr2); // 7,6,15,4,13,2,1 console.log(arr2.sort()); // 1,13,15,2,4,6,7 问题:只能通过第一位排列。(对首字母的 unicode 编码进行排序) 解决:sort方法不稳定,设计的时候就是这么设计的,可以通过回调函数进行规则设置。 console.log(arr2); console.log(arr2.sort(function (a,b) { return a-b; //升序 //b-a:降序 })); 迭代方法 代替 for 循环。 every every()他的返回值是一个 boolean 类型值。而参数是一个回调函数。 参数有三个。名字随便起,但是表示的意思还是这样顺序的。 var arr = ["关长","张飞","赵子龙","马超","黄忠"]; // function (element,index,array) // element:数组元素的值 // index:索引 // array:调用这个方法的整个数组对象(一般不用) arr.every(function(fff,www,ggg) { console.log(fff); console.log(www); console.log(ggg); return true; }); // 关长 // 0 // ["关长", "张飞", "赵龙", "马超", "黄忠"] // 张飞 // 1 // ["关长", "张飞", "赵龙", "马超", "黄忠"] // 赵龙 // 2 // ["关长", "张飞", "赵龙", "马超", "黄忠"] // 马超 // 3 // ["关长", "张飞", "赵龙", "马超", "黄忠"] // 黄忠 // 4 // ["关长", "张飞", "赵龙", "马超", "黄忠"] var arr = ["青花瓷", "一路向北", "轨迹"]; var flag = arr.every(function (ele, index) { // 只要有一个没满足条件,就返回false ele.length > 2; }); console.log(flag); // false filter filter返回值是一个新数组。return为 true 的数组。 var arr = ["关长","张飞","赵子龙","马超","黄忠"]; var arr1 = arr.filter(function (ele,index,array) { if(ele.length>2){ return true; } return false; }); console.log(arr1); // ["赵子龙"] foreach foreach遍历数组(无返回值,纯操作数组中的元素) var arr = ["关长","张飞","赵子龙","马超","黄忠"]; var str = ""; arr.forEach(function (ele,index,array) { str+=ele; }); console.log(str); // 关长张飞赵子龙马超黄忠 map map有返回值,返回什么都添加到新数组中。 var arr = ["关长","张飞","赵子龙","马超","黄忠"]; var arr2 = arr.map(function (ele,index,array) { return ele+"你好"; }) console.log(arr2); // (5) ["关长你好", "张飞你好", "赵子龙你好", "马超你好", "黄忠你好"] some some有返回值,如果函数结果有一个是true,那么some方法结果也是true。 var arr = ["关长","张飞","赵子龙","马超","黄忠"]; var flag = arr.some(function (ele,index,array) { if(ele.length>2){ return true; } return false; }) console.log(flag); // true push 向数组的末尾添加一个或更多元素,并返回新的长度。 注意: 新元素将添加在数组的末尾。 注意: 此方法改变数组的长度。 提示: 在数组起始位置添加元素请使用 unshift() 方法。 pop 删除数组的最后一个元素并返回删除的元素。 注意:此方法改变数组的长度! 提示: 移除数组第一个元素,请使用 shift() 方法。 了解方法 concat() //把参数拼接到当前数组 //新数组 = 数组1.concat(数组2); slice() //从当前数组中截取一个新的数组,不影响原来的数组,参数start从0开始,end从1开始 //新数组 = 数组1.slice(索引1,索引2); splice()//删除或替换当前数组的某些项目,参数start,deleteCount,options(要替换的项目) //新数组 = 数组1.splice(起始索引,结束索引,替换内容); indexOf()、lastIndexOf() //如果没找到返回-1 //索引值 = 数组.indexOf/lastIndexOf(数组中的元素); forEach() // 数组每个元素都执行一次回调函数。 清空数组 var array = [1,2,3,4,5,6]; // 方法一:删除数组中所有项目 array.splice(0,array.length); // 方法二:length属性可以赋值,其它语言中length是只读 array.length = 0; // 方法三: array = []; //推荐

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

JavaScript基础(四)函数

函数 函数的定义 //第一种:(函数的声明)第一种定义方法最强大,定义完毕后,在哪里使用都可以,无位置限制。 function fn1(){ console.log("我是第一种定义方法!"); } //第二种(函数表达式:匿名函数) :后两种定义方法是有局限性的。(使用函数必须在定义函数之后) var fn2 = function (){ console.log("我是第二种定义方法!"); }; // 注意分号 function (){ console.log("我是第二种定义方法!"); }(); // 第二种方式的调用方式之一:函数的自调用 //第三种 var fn3 = new Function("console.log('我是第三种定义方法!')"); 函数的调用 函数名(); 函数名 要遵循驼峰命名法。 不能同名(函数重载),否则后面的函数会覆盖前面的函数。 //打印函数名,就等于打印整个函数。 console.log(fn); //打印执行函数,就等于打印函数的返回值。 console.log(fn()); 形参和实参 形参不需要写 var. 形参的个数和实参的个数可以不一致 。 返回值 1. 如果函数没有显示的使用 return 语句 ,那么函数有默认的返回值:undefined2. 如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值也是:undefined. 变量和作用域 全局变量:在 script 使用 var定义的变量和没有 var 的变量(所有的 script 共享其全局性,js里面没有块级作用域概念,只有全局作用域和局部作用域)。 隐式全局变量:在 script 没有 var 的变量。 function fn(){ var a = b = c = 1; // b和c就是隐式全局变量(等号) var a = 1; b = 2; c = 3; // b和c就是隐式全局变量(分号) var a = 1 , b = 2 , c = 3; // b和c就不是隐式全局变量(逗号) } (全局变量是不能被删除的,隐式全局变量是可以被删除的) var num1 = 10; num = 20; delete num1; delete num2; console.log(typeof num1); // number console.log(typeof num2); // undefined 局部变量:函数内部用 var 定义的变量和形参。 变量声明提升(预解析) 作用:查看语法错误。js的解析器在页面加载的时候,首先检查页面上的语法错误。把变量声明提升起来。变量声明提升和函数整体提升。 变量的提升 只提升变量名,不提升变量值。 consolas.log(aaa);// 打印的结果是 undefined ,因为只提升变量名,不提升变量值。 var aaa = 111; 在函数范围内,照样适用。 函数的提升 function 直接定义的方法:整体提升(上面说的第一种函数定义的方法). fn(); var aaa = 111; function fn(){ //变量声明提升在函数内部照样实用。 //函数的就近原则(局部变量作用域),打印的aaa不是111,而是 undefined。 console.log(aaa); // undefined var aaa = 222; } 预解析会分块: 多对的 script 标签中函数重名的话,预解析不会冲突。也就是预解析的作用域是每一个的 script 标签。 var先提升,function再提升: 示例: console.log(a); // 输出a函数体 function a() { console.log("aaaaa"); } var a = 1; console.log(a); // 输出1 打印第一个结果的时候,var会提升,之后 function 再提升,但是函数a和变量a重名,function的a在后面覆盖掉变量a,所以第一个输出 a 函数体. 第二个前面var a = 1;提升之后,这个位置就相当于只有 a = 1; 赋值,所以第二个打印1. 匿名函数 //1.直接调用 (function (){ console.log(1); })(); //2.绑定事件 document.onclick = function () { alert(1); } //3.定时器 setInterval(function () { console.log(444); },1000);

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

python基础知识

1、print()函数print函数用于向控制台、python解释器、cmd命令行输出你想要输出的内容。print函数有输入参数,可以是字符串、数字、变量等等,也可以是它们的混合,不同对象之间可以使用,来分隔,print函数遇到,的时候会输出一个空格来作为分隔输出的效果。注意:在print函数中,如果输入的内容是可以继续计算或者合并的,那么python会先计算或者合并之后再输出。如:print(100+200)print('a'+'b')会输出数字300以及字符串'ab'2、input()函数用于从命令行、python解释器获取用户的输入,从subline text中无法输入。用户的所有输入都会被当做是str类型,即字符串类型,用户可以将input的输入内容放入变量中,即:name=input()用于保存输入的内容用作后续代码的指代。同时,为了更友好的界面,可以给input函数输入参数值,参数值可以是一个字符串,也可以是一个变量的指代,用于在提示用户输入的时候给出详细的说明,即:name=input('inpurt your name:')或者i='please input here:' , name=input(变量i)。3、组织方式python的组织方式是通过统一缩进,主旨是简洁优雅。4、数据类型和变量====整数和浮点数:整数分为正整数、负整数、0浮点数有精度问题,很大的浮点数可以用科学计数法标记,其中的10使用e来表示,即:12300000 = 1.23e7 ,或者类似2.35e-5等等====字符串:字符串,顾名思义,是一串字符序列,使用单引号或者双引号包括起来,外围的单引号或者双引号不算字符串的内容。如果字符串内容有单引号,那么外围要使用双引号包围,反之亦然,如果字符串内容中既有单引号又有双引号,则要使用\来转义其中一个引号如:' i\'am a "good" man ' ,使用\'来表示转义单引号====字符串+转义字符:在print函数中无法通过回车来体现最终打印字符串的换行,必须使用\n来表示换行,使用\t表示制表符,\单引号或者双引号,\\表示\符号注意:默认情况下,一个字符串中的\转义字符是会转义的,转义规则根据上述说明。但是如果在字符串前面加上r,则表示不对字符串内容做转义如:默认转义,print('line1\'line2')---->line1'line2强制不转义,print(r'line1\'line2')----->line1\'line2(可用于re的过滤规则中)这种情况下,不会转义:print('line1\\'+'nline2')------>line1\nline2====字符串+''''''实现简化换行:如果要输出一个段落,涉及字符串内部的多处换行,可以使用\n来实现,也可以使用print(''' ''')来实现,里面的字符串根据实际内容直接回车如:print('''这里是根据传入的页数,形成了所有的链接这里是server端这是一张新图片,准备下载''')====布尔值:True和False,用于各种判断,意味着一件事件为真或者为假,如3>2为真,2==0为假逻辑运算and,or,not,逻辑运算会与布尔值结合计算,如True and True 的结果为True注意:在python中,1可以被认为是True,0被认为是False(可以计算),其他值即不是True也不是False注意is是表示两边是同一个对象====空值:python中的空值使用None表示,注意,None不是0,对于0而言是有意义的,而None是一种特殊的属性,意味着空====变量:python支持多种数据类型,有内置原生数据类型,也有自定义扩展数据类型,任何类型的数据都可以看成一个对象,通过变量来指向它,对变量进行赋值就是让某一个变量指向某一个对象,建立他们两之间的关系。变量类似一个指针,指向某一个内存对象,python是动态语言,所以可以指向不同类型的对象,如str,int,float,list等等,java是静态语言一旦int a,那么a只能指向ini类型对象a='hello' , b=a ,意味着把a指向的对象的地址赋给b,或者说,让b指向a所指向的对象,这时候'hello'对象有两个指向自己的指针。如果此时a='world',那么print(b)还是等于'hello'====常量:约定俗成的使用全部大写变量名来表示常量,如PI对于除法/,python3中是不会取整的,python2是取整的对于地板除//,python3和2都是取整的使用%获取余数5、字符串编码问题====历史:在计算机历史上,计算机被设计成拥有处理数字的功能,计算机底层1个字节定义成8个位,1个字节可以表示的数字最大是255,如果需要表示更大的数字,就需要更多的字节,2个字节可以表示最大65535,4个字节可以表示42亿左右。根据计算机的原本设计是只能处理数字,如果要处理文本,即处理字符串,则需要把字符串与数字进行映射,即通过编码的方式记录每一个字符对应的数字。计算机是美国人发明的,所以当时只需要处理英文字符串,所有英文字符,包括字母大小写、数字、符号等等加在一起一共形成了127个字符,这127个字符通过1个字节就可以完全表示。通过1个字节对应的1个整数,映射到不同的字符,这种编码方式就是ASCII编码方式。随着计算机的发展,不同国家都在使用,都想通过计算机输入本国的语言,如中文,对于中文而言,中文的字符至少需要2个字节即至少需要65535个数字才能表示,所以中国为中文定制了GB2312编码方式,用于将中文编码到计算机的底层整数。同样的,不同国家有不同的编码方式,这就导致:同样的1个编码整数可能会在不同国家有不同的表示,而且,如果多个国家的程序放在一起,计算机就无法识别某一个字符串是属于英文还是中文还是其他国家的字符。为了解决不同国家定制不同的编码标准,出现了unicode统一字符编码标准,unicode标准常常使用2个字节表示1个字符,将世界上所有的语言都包含到这个编码标准中,这样不论计算机在哪里使用,不论计算机使用的是哪种语言,都不会出现混乱和冲突的问题。对于一些生僻的字符,unicode可能需要使用4-6个字符来表示。而如果单纯只使用unicode编码的时候,会出现空间浪费的问题,如果程序全部使用英文编写,所有英文字符默认2个unicode字节对应1个英文字符。所以使用unicode虽然可以很好的解决不同语言之间互通的问题,但是会带来空间浪费和效率不高的问题。这时候就需要使用UTF-8可变长编码方式,使用UTF-8的时候,如果是中文就是2个字节对应1个中文字符,如果是英文就是1个字节对应1个英文字符,即UTF-8的字节使用数量是根据实际使用的语言来灵活变化的,这种好处尤其体现在数据的保存、压缩、传输上。所以现在的计算机保存的数据都是UTF-8编码方式,一旦被程序调用的时候,文件中的数据则转换成unicode编码方式在内存中被处理,在处理完毕再次保存之前又被转换成高效的UTF-8编码方式。我们从网站上获取网页的时候,网页html是以源代码的形式传回给我们的浏览器,源代码中经常有:<meta charset="utf-8" /> 表示该网页使用UTF-8编码的方式来传输数据。====python字符串的编码:python3版本中,所有的字符串str类型对象都是使用unicode编码方式,即python中的所有字符串,都有对应的unicode整数,如:unicode是针对每一个字符做编码的,可以通过ord()函数对任意一个字符求出对应的unicode整数,也可以通过chr()输入unicode整数来得到对应的unicode字符当然,也可以这样写:'\uxxxx'其中要放入unicode整数的十六进制数,如,25991的十六进制数是0x6587:====编码转换:python在内存中的数据都是unicode编码,都是str类型的对象。而数据在保存或者网络传输的时候,必须转换成byte类型的字节流的形式,把unicode转换成byte类型需要依据不同的内容做不同的编码,所有byte类型的对象都是b开头,如:'abc'是str类型的对象,是unicode编码,是英文,所以转换成可传输的字节流就是'abc'.encode('ascii')---->b'abc',此时ascii编码中,1个字节对应1个英文字符'中文'是str类型的对象,是unicode编码,是中文,所以转换成可传输的字节流就是'中文'.encode('utf-8')---->b'\xe4\xb8\xad\xe6\x96\x87',此时utf-8编码中,使用3个字节表示1个中文字符------------------------------------------------------------------------------------------------------'中文'.encode('gb2312')---->b'\xd6\xd0\xce\xc4' ,此时gb2312编码中,使用2个字符表示1个中文字符总结:在计算机内存中,在python3中,所有str对象都是unicode编码,这是为了使不同国家语言可以互通,unicode编码一般是2个字节编码1个字符。而在传输、保存数据的时候,需要把unicode编码的字符转换成其他的编码方式,英文可以转换成ascii或者utf-8,中文可以转换成gb2312或者utf-8,变成可传输的字节流。使用不同的编码方式,1个字符使用的字节数量不同。一般情况下,我们都使用unicode和utf-8这两种,因为中文和英文都可以使用utf-8方式编码。即:str对象.encode('utf-8')可以变成字节流byte类型对象以b开头, byte对象.decode('utf-8')可以变成unicode字符的str类型对象用于计算机和程序的处理,所以在hello.py文件的开头都有:#coding:utf-8就是告诉python解释器:使用utf-8编码方式来decode到unicode来处理,然后将unicode的数据encode到utf-8来保存和传输====python的格式化字符串:last=72today=85rate=(today-last)/lastprint('小明的成绩从去年的%d分提升到了今年的%d分,增长百分比是:%.1f%%' %(last,today,rate))6、list和tuple====list的性质:list是python的内置数据类型,翻译成列表或者数组。list是一组数据或者一组对象或者一组元素的序列,同样的元素不同的排列是不同的列表。列表的元素数量可以通过len(a)来获得,list是可变长数组,可以随时通过append在末尾增加元素,通过pop(i)弹出位置i的元素默认是末尾,通过insert(i,xx)在位置i插入xx元素。除此之外,list还是混合类型数组,即数组内部可以允许不同类型的元素,如:a=[1,True,'abc',2.2],此时的a是一个指向一个list地址的变量(性质上是指针)。list通过下标0~len-1的范围来获取每一个元素。list可以通过-1,-2来从尾部开始获取元素,-1表示倒数第1个元素,-2表示倒数第2个元素,以此类推。list中可以放任何类型的对象,除了python内置的整数、浮点数、布尔值、字符串等,还可以是list,tuple,dict,其他自定义数据类型等等。如果list中还有一个list,则意味着内部的list是一个二维数组,如果内部list的一个对象还是一个list,则最内部list是三维数组,以此类推,通过a[1][2]来获取二维数组的元素。====tuple的性质:tuple的性质和list很相似,最大的不同在于tuple更严格、更安全、数据只能取不能增删改,即tuple一旦初始化后则无法改变内容,而list可以随时增删改元素。====注意:二义性的tuple符号:list在创建的时候使用[],tuple在创建的时候使用(),如果是创建一个空list则是a=[],如果是创建空tuple则是a=(),如果创建一个只含有1个元素的tuple,不应该写成a=(1)这会被python解释成a=1,a是一个int类型的对象因为python遇到()的时候有二义性,到底是tuple还是普通的小括号,python规定当做小括号使用,所以声明一个只有1个元素的tuple应该是:a=(1,)注意不要缺少这个逗号。====注意:“可变的”tupletuple的不可修改指的是每一个tuple中的元素所指向的对象都不发生地址变化,但是所指向的对象的内容却可以改变,如:a=('a','b',['A','B'])a[2][0]='X'a[2][1]='Y'print(a) -- > ('a','b',['X','Y'])这种修改是合法的,因为对于tuple a而言,a[2]这个元素地址并没有发生改变,即并没有指向其他的list,而这个未改变地址的list的内容发生改变并不影响tuple的规定。7、条件判断if,elif,else判断语句,用于分支判断,if可以理解成判断后面的语句是否为真,如果是真则执行if语句块,如果不为真就一定为假,则执行else语句块,使用elif可以增加多个判断条件。连用多个if和elif的判断逻辑类似于ACL访问控制列表,判断顺序也是自上而下,一条没有满足即顺延到下一条判断条件,一旦某一条判断条件是真,则不再进行后续判断,如果所有if和elif都判断为假,则用最后的else作为permit any含义。注意条件判断后面不要遗漏:冒号,条件判断还可以简写成if x: 这个x只要是非零整数、非空列表、非空tuple、非空字符串等等,都认为是True,否则认为是False。input()函数用于获取用户输入,无论用户输入的是数字、字符、还是字符串等等,都被input函数以str的类型返回。可以通过eval()函数获取一个字符串的值,如:'2'就是2,'a'会得到变量a8、循环python中的循环有两类====for循环:for循环用于遍历一个序列,将序列中的每一个元素赋值给自定义的变量以便操作序列中的所有元素值,如:注意:一般会使用list(range(10))来构造一个10个元素的列表,因为从0开始所以是0~9的10个元素。for循环的循环执行依赖于明确的范围遍历(无法依赖条件判断)====while循环:while循环的执行依赖于while关键字后面的条件判断,当为真的时候执行循环体,执行完毕后再次条件判断,为假的时候跳出循环,所以循环体内部需要有一定的限制条件或者手段来保证有限次的循环后可以跳出,即while循环的执行依赖于条件判断+循环体内部限制条件注意:跳出while循环的时候,一定是第一次不满足循环条件判断的时候====break:在循环体内部使用break可以跳出当前一层循环,用于特殊、有需要的程序执行分支流程====continue:在循环体内部使用continue可以省略剩余的循环体语句并立即开始下一次循环,如果是for就中断并提前遍历下一个元素,如果是while就中断并提前执行下一次条件判断注意:大量的、不加规划的使用break和continue的确会导致程序的逻辑、执行流程混乱,加重代码的复杂度以及后期debug的工作量。另外,就像无限迭代会导致机器崩溃一样,无限循环也会导致机器崩溃,所以编写循环首要注意的就是是否可以在必要的时候跳出循环体,尤其是while循环体中是否有足够的限制条件和手段。9、dict和set就像list和tuple非常的类似,并且都是python的内置数据类型一样。dict和set也是python的内置数据类型,也一样非常类似。====dict:dict在python中称为字典,是一种key-value对,其实类似于哈希表,即一个输入(key),有着唯一的输出(value),中间通过hash算法来完成唯一的映射。dict使用{}来表示,里面填写每一个key-value对使用逗号分隔。dict中的key就是哈希表中的输入或者关键字,dict使用哈希算法将key映射成唯一的内存地址,该内存地址上可以保存其他对象即value,所以key被要求不可变(即一旦初始化即不可再改变),如整数、字符串、元祖tuple等等,而value的值却是可变的,但若value变化多次则会以最后一次的值为准。在dict中,key是没有排序的,即无法使用dict[0]这种类似list和tuple的方式来获取第1个元素,dict只能使用d[key名称]的形式来获取这个key所对应的value。dict使用d[key名称]=value的方式来为一个dict新增键值对,也可以使用del d[key]的方式删除一个键值对,或者是d.pop(key)的方式弹出一个键值对,dict使用d[key名称]的方式来访问这个key对应的value,如果没有该key则会报错,所以访问方式还可以是:key in d 使用布尔判断是否含有此key,或者是d.get(key,-1)获取d的key的value,如果没有key则返回-1,默认返回None无法在python解释器中显示结果。遇到任何有联系的两个对象,都可以使其一成为key,另一个成为value放入dict中,在dict中的查找速度是非常快的基本等于O(1)。====set:set在python中称为集合,更确切的说,就是一些不重复的对象的集合,之所以不说是序列,是因为set是无序的,即无法使用s[0]这种序列访问方式来访问,就像dict一样,也是无序的。同时,set的构造使用{}来表示,和dict一样,但是set的对象并不是dict那样的键值对,事实上,set的对象只有key而没有value。可以使用s=set(某个序列)函数来构造一个集合,输入需要是一个序列,可以是list、tuple、range(10)等。set最重要的特性是:1、set中对象无重复2、set作为集合,可用于数学上的集合运算,如交集&,并集|交集:取s1和s2中共有的部分作为结果,即交集是s1的子集,也是s2的子集并集:将s1和s2所有元素整合并消除重复,即s1是并集的子集,s2页是并集的子集3、set可以增加或者减少对象,s.add(100), s.remove(2)如果新增多个重复的对象,set会自动过滤====注意:关于不可变对象:首先,对象不可变指的是某个对象一旦被构造并被初始化值之后,就不能再改变这个对象的地址以及这个对象的值,如:整数、字符串、tuple、dict的key等等。其次,不可变对象的一些函数如果涉及到需要改变对象的值,则一般会复制一份同值的对象并返回,而原来的不可变对象还是没有改变值,以此来保证对象的不可变性。对于可变对象,对象的函数如果涉及改变对象的值,则直接在原有对象上进行改变。如:因为str1不可变,所以replace涉及修改值的时候返回了另一个对象因为list1可变,所以直接在list1对象上直接修改值,并不返回另一个对象

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

JVM调优基础

1. JVM命令功能 jcmd help jhat: 读取内存堆转存 jmap: 提供转存和内存使用信息 jinfo:查看jvm的系统属性,也可以是设置系统属性,可用于脚本 jstack: 转存java进程信息,可用于脚本 jstat: 提供GC和类装载活动的信息,可用于脚本 jvisualvm: 可视化工具 jstat -J-Djstat.showUnspported=true -snap 5376 -- 获得监控信息 -XX:ReservedCodeCacheSize=N 标志可以设置代码缓存最大值-XX:InitialCodeCacheSize=N 代码缓存从初始大小开始分配 1.1 常用信息 1.错误信息:C: C帧, j: java帧 V: VM帧 v:VM生成的stub帧,J:其它帧,含java帧(编译) 2: TPS:每秒事物数,比如执行了dml操作,那么相应的tps会增加 RPS: 每秒请求数,并发数/平均响应时间 OPS:每秒操作次数 QPS是指每秒内查询次数,比如执行了select操作,相应的qps会增加。 PV 是指页面被浏览的次数,比如你打开一网页,那么这个网站的pv就算加了一次; 3 vmstate 1: 单个线程,CPU内存等监控, iostat -xm 5 , nicstat 5: 监控网络信息 4 JVM内部线程状态: _thread_uninitialized _thread_new _thread_in_native _thread_in_vm _thread_in_java _thread_block _<thread_state_type>_trans 5.JVM状态 not at a safepoint: 正常执行的状态 at safepoint: 所有线程阻塞,等待VM完成专门的VM操作(VM operation) synchronizing : VM接到一个专门的VM操作请求,等待VM中所有现场阻塞 2. JVM保留内存和分配内存之间的差别: 编译是基于JVM计数器: 方法调用计数器和方法中的循环回边计数器, 当方法或循环 编译的时候,就会进入编译队列,队列有一个或多个后台线程处理.也就是异步的,并不是严格先进先出,调用计数次数多的方法有更高优先级,也就是PrintCompilation输出中ID乱序的原因. OSR(on-stack Replacement): 在循环进行的时候还能编译循环,在循环代码编译结束后,JVM会替换在栈上的代码,循环的下一次就行快的多的代码 -XX:CompliThreshold=Nclient默认1500,server默认10000,一般不用修改),这个数值是回边计数器和方法调用次数的总和 -XX:PrintCompilation(默认false):每编译一个循环和方法就输出编译内容 -XX:CICompilerCount=N :JVM 处理队列的线程总数 -XX:+BackgroundCompilation(默认为true,即异步处理,也可以改为false,一个方法适合编译就一直等到他确实被编译) jstat -compiler 8895 输出这个pid的编译过的方法,有时也会出现编译失败的方法 jstat -printcompilation 8895 1000 (每秒钟输出一次编译的方法) -XX:-Inline (默认开启,关闭的话严重影响性能)-XX:PrintInlining 生成内联信息 方法是否内联取决于: 多热和它的大小,只有字节码小于325字节才会或者小于35字节-XX:MaxFreqInlineSize=N -XX:MaxInLineSize=N 逃逸分析-XX:+DoEscapeAnalysis(默认为true) 逆优化 (意味着编译器不得不撤销之前的优化): (1) 代码状态为"made not entrant"(代码被丢弃) -原因: 可能和类与接口的工作方式有关,也可能与分层编译的实现有关 (2) "made zombie"(产生僵尸代码) client编译的结果后来server编译更优化的结果 编译级别: C1编译器有3种级别,所以总有5种编译级别 0: 解释代码 1: 简单的C1编译代码 2: 受限的C1编译代码 3: 完全的C1编译代码 4: C2编译代码 目前主流的4个GC算法: 1: Serial : -XX:+UseSerialGC 2: Throughput(Parallel): 7之后默认,使用多线程收集Eden区, -XX:+UseParalleGC -XX:+UseParallelOldGC 3: Concurrent (CMS): 修改之前UseParalleGC算法收集Eden区,改用 -XX:UseParNewGC收集Eden, -XX:+UseConcMarkSweepGC 后台线程扫描Old区的垃圾对象,停顿时间少, 问题: (1)占用CPU线程资源,(2)内存碎片化严重,最后变成Serial(间隔时间长),整理好内存之后重复之前 4: G1: -XX:+UseG1GC, 属于Concurrent收集器,老年代的收集工作由后台线程完成,大多数不需要暂停应用线程,由于老年代被划分到不同的 区域,G1收集器通过将对象从一个区域复制到另外一个区域,完成对象的清理工作,这也意味着G1实现了堆的压缩整理(至少是部分整理) System.gc() 会触发Full GC -Xms4096m -Xmx4096m 设置一样大就不需要估算堆是否需要调整大小了 -XX:NewRatio=N(默认2): 新生代与老年代的空间占用比率 Initial Yong Gen size = Initial Heap Size / (1+NewRatio) --> 默认新生代占 1/3 -XX:NewSize=N 直接设置新生代初始的大小 -XX:MaxNewSize: 设置新生代最大大小 -XX:PermSize=N, -XX:MaxPermSize=N 设置永久区的大小 -XX:MetaspaceSize=N -XX:MaxMatespaceSize=N 调整 除了SerialGC之外几乎所有的GC都是使用多线程,启动线程数由 -XX:ParalleGCThreads=N控制-XX:+UseParallelGC -XX:+UseParNewGC -XX:+UseG1GC 收集新生代空间-XX:+UseParallelOldGC 收集老年代空间估算公式: ParalleGCThreads = 8 + ((N-8)*5/8), 每超出5/8个CPU启动一个新的线程(可能会略高,需适当调整) -XX:-UseAdaptiveSizePolicy(默认开启) 可以在全局范围内关闭自适应调整功能,如果堆容量最大值和最小值设置同样的值,与此同时,新生代的最大值和最小值也设置为同样的值,自适应功能将会被关闭 -XX:PrintAdaptiveSizePolicy: 一旦发生GC会在日志中包含GC不同空间调整的信息 -verbose:gc 或 -XX:+PrintGC -XX:+PrintGCDetails(默认关闭) -XX:+PrintGCTimeStamps -XX:+PirntGCDateStamps -XX:+UseGCLogfileRotation -XX:NumberOfGCLogfiles=N -XX:GCLogfileSize=N 组合使用可以控制循环输出日志 文件大小不足8kb按照8kb算 查看日志可以使用 gchisto 或者jstat -gcutil pid 1000 每秒输出日志信息 GC回收算法 1. Throughput 收集器 回收新生代的垃圾 Minor GC 回收老年代垃圾 Full GC -XX:MaxGCPauseMillis=N 设定应用可承受最大停顿时间 -XX:GCTimeRatio=N 设置你希望应用程序在垃圾回收上花费多少时间(与应用线程的运行时间相比) 公式: ThroughputGoal=1-1/(1+GCTimeRatio) 默认是99,也就是运行程序占99%,只有1%的时间消耗在垃圾回收上 2. CMS收集器 CMS会对新生代的对象进行回收 ParNew(所有线程都会被暂停) CMS会启动一个并发线程对老年代空间进行垃圾回收,(不会内存整理) 如有必要,CMS会发起 Full GC CMS收集步骤: 1: Init-mark: 找到堆中所有垃圾回收根节点对象 2: current-mark: 和应用程序并行,标记,(可能还会产生垃圾) 3: preclean-start: 预处理,与应用程序并行 4: remark(多个阶段),不是并发,STW 5: concurrent-sweep: 与应用程序并行 6: concurrent-reset: 并发重置 CMS可能会产生的问题: concurrent mode failure:新生代发生GC,同时老年代又没有足够的空间容纳晋升的对象时,CMS GC就会退化成Full GC,所有的应用线程都会暂停,老年代对象进行回收,这个操作是单线程的,所以非常耗时 老年代有足够的空间容纳晋升的对象,但是空间非常碎片化,导致晋升失败. 这时新生代暂停了所有的应用线程,专门在老年代整理碎片内存,好消息是内存碎片整理完了,但是会有很长时间停顿,这比并发模式失效停顿的时间还长.(因为并发模式失效时只需要整理堆里无效的对象) 针对并发模式失效的调优: 增大老年代空间 以更高的频率运行后台回收线程 使用更多的后台线程 注意点:1. CMS与其他回收算法的显著不同就是:除非发生Full GC,否则CMS的新生代大小不会调整.CMS的目标就是尽量避免Full GC, 可以使用: MaxPauseMllis=N和GCTimeRatio=N来确定使用多大的堆和多大的空间 2. 给后台线程更多的运行机会: -XX:CMSInitiatingOccupancyFraction=N和-XX+UseCMSInitiatingOccupanyOnly(默认70,即CMS在老年代空间占70%时启动并发收集周期调整) 调整后台线程: -XX:ConcGCThreads=N增加后台线程,ConcGCThreads=(3+ParallelGCThreads) / 4 3. CMS不会处理永久代的垃圾,如果耗尽会产生一次Full GC来回收垃圾,可以设置: -XX:+CMSPermGenSweepingEnable(默认false)标志开启和老年代同样的回收方式,后台开启一组线程并发回收永久代中的垃圾,同时配合:+XX:CMSInitiatingPermOccupancyFrantion=N指定在永久代占用达到比例值时开启回收线程. java8 CMSPermGenSweepingEnable标志默认开启 4: 增量式CMS,(java8种不推荐使用) 当CPU资源有限,后台线程会间歇性暂停,让出一部分CPU给应用线程 开启: -XX:+CMSIncrementalMode, 设置: -XX:CMSIncrementalSaftyFactor=N,-XX:CMSIncrementalDutyCycleMin=N,-XX:CMSIncrementalPacing可以控制GC线程为应用线程让出多少CPU G1收集器 分区(Region)一般分为2048个区域,专注于垃圾最多的分区,用最少的时间回收最多的垃圾 新生代进行回收时,要么被回收,要么被晋升,新生代采用分区机制的部分原因是采用预定义的分区能够便于代的大小调整 主要包括4种操作: 1.新生代垃圾收集 2.后台收集,并发周期 3.混合式垃圾回收(不仅进行新生代的GC同时也回收部分后台扫描线程标记的分区) 4.以及必要的Full GC 操作步骤: 1:initial-mark(STW) 2: root-scan(并发) 3: conc-mark 4:remark 5: conc -clean G1注意: 1: 并发模式失效:,在G1启动标记周期,但老年代在周期完成之前就被填完,G1会放弃标记周期,(GC-concurrent-mark-abort)2:晋升失败: G1完成了标记阶段,开始启动混合式垃圾回收,清理老年代分区,不过,老年代空间在垃圾回收释放出足够内存之前就会被耗尽. 一般都是混合式回收之后就是Full GC 3:疏散失败:进行新生代垃圾回收时,S区和老年代中没有足够的空间容纳所有的幸运对象.这表明堆已经几乎用完或者碎片化了.转用Full GC,性能下降,最简单的解决办法就是增加堆 4:巨型对象分配失败也可能会导致Full GC G1 调优: G1调优的主要目标就是避免发生并发模式失败或者疏散失败 -XX:MaxGCPauseMillis=N(默认200ms,这个CMS有所不同) 1:调整G1的后台线程数,可以使用ParallelGCThreads设置运行的线程数,计算方式ConcGCThreads=(ParallelGCThreads+2)/4 这个和CMS也不同 2: -XX:InitiatingHeapOccupancyPercent=N(默认45),堆占用比例,如果设置过高会陷入Full GC泥潭中,因为并发阶段没有足够的时间在剩下的堆空间被填满之前完成垃圾回收,如果设置过小又会以超过实际的节奏在后台大量处理 3:调整G1收集器混合式垃圾收集周期:混合式垃圾收集取决于三个因素(1)有多少分区被发现大部分是垃圾对象,默认超过35%就会标记为可进行垃圾回收,实验版标志: -XX:G1MixedGCLiveThresholdPercent=N (2)G1垃圾回收分区时最大混合式GC周期数,参数 -XX:G1MixedGCCountTarget=N(默认8),减少该值可以解决晋升失败的问题(代价是混合式GC周期的停顿时间会更长) (3)GC停顿可忍受的最大时常,参数-XX:MaxGCPauseMillis 4:2种情况下会被移动到老年区: (1):S区实在太小,S区被填满之后,Eden区剩下的活跃的对象直接放到Old区,(2)在S区经历的GC周期的个数上限(Tenuring Threshold) 5: S区是新生代的一部分,跟堆内存的其他区域一样,JVM可以对他动态调节,参数: -XX:InitialSurvivorRatio=N(默认8)决定, survivor_space_size=new_size / (initial_survivor_ratio+2) JVM可以增大S区空间直至最大上限, -XX:MinSurvivorRatio(默认3)设置(注意参数在分母,名字不直观),maximum_survivor_space=new_size / (min_survivor_ratio + 2), -XX:TargetSurvivorRatio=N可以在Survivor空间调整之后能保证垃圾回收之后有50%的空间是空闲的. 6: -XX:InitialTenuringThreshold=N可以设置初始晋升阈值(Throughput和G1的默认值7,CMS默认值是7),JVM最终会在1和最大阈值(-XX:MaxTenuringThreshold=N)之间选择一个合适的值, 对于Throughput和G1,最大值默认15,CMS最大默认6) 7:-XX:PrintTenringDistribution标志可以在GC中增加这些信息 8: TLAB的大小由三个因素决定: (1)应用线程的线程数(2)Eden空间的大小(3)线程分配率,默认开启,-XX:-UseTLAB可以关闭. -XX:TLABSize=N可以显示的指定TLAB的大小(默认为0,由Eden区的大小动态计算出),这个标志只能设置TLAB的初始大小,为了避免每次GC时都调整TLAB的大小可以使用 -XX:-ResizeTLAB,TLAB调整时,最小容量可以使用:-XX:MinTLABSize=N设置(默认2kb),最大容量略小于1GB 9: -XX:+PrintTLAB输出信息 G1分区大小: size=1<<log(初始堆的大小/2048), 分区最小1MB,最大不能超过32MB, 堆的大小: 堆的大小 Region Size < 4GB 1MB 4GB - 8GB 2MB 8GB - 16GB 4MB 16GB - 32GB 8MB 32GB - 64GB 16MB > 64GB 32MB G1分区的大小可以通过-XX:G1HeapRegionSize=N设置(默认0,动态计算出),选择合适的大小,使分区数量接近于: 2048个 堆内存 1.jmap -dump:live,file=/path/heap.dump.hprof pid, jmap有live选项会在堆转储之前强制执行一次Full GC, jcmd默认就会这么做 jcmd pid GC.heap_dump /path/heap_dump.hprof -XX:+HeapDumpOnOutOfMemoryError(默认false)会在抛出OutofMemoryError时转储 -XX:HeapDumpPath=/path 指定堆转储位置,默认java_pid.hprof -XX:+HeapDumpAfterFullGC:在运行一次Full GC之后生成一个堆转储 -XX:+HeapDumpBeforeullGC:会在一次Full GC之前生成一个堆转储文件 3: Exception in thread 'main' java.lang.OutOfMemoryError: GC overhead limit exceeded:原因: (1) 花在Full GC上的时间超出了-XX:GCTimeLimit=N(默认98,也就是98%的时间花在了GC上了) (2):一次Full GC回收的内存量少于-XX:GCHeapFreeLimit=N设置的值,默认值2,即意味着如果Full GC期间释放的内存不足堆的2%,(3)上面2个条件连续5次Full GC都成立(这个值无法调整) (4):-XX:+UseGCOverHeadLimit标志的值为true(默认true) 请注意:所有四个条件都满足的时候才会报错,如果连续4次Full GC都成立,作为释放内存的最后一搏,JVM中所有的软引用都会在第五次Full GC之前被释放 减少内存使用(减少对象大小,对象延迟初始化,规范化对象) 1.对普通对象,对象头字段在32位JVM上占8字节,在64位JVM上占16字节,对于数组,对象头在32位JVM以及堆小于32GB的64位JVM上占16字节,其他情况是64字节 2.不可变对象:基本的数据类型Double,Boolean,以及一些基于数值的类型,BigDeciaml,String,像这类不可变对象的单一化表示,就被称为标准化(canonical)版本,类似有String.intern 例如: 创建一个Map来保存该对象的标准化版本,为防止内存泄漏,采用WeakHashMap class ImmutableObject{ WeakHashMap<ImmutableObject,ImmutableObject> map = new WeakHashMap<>(); public ImmutableObject canonicalVersion(ImmutableObject io){ synchronized (map){ ImmutableObject cv = map.get(io); if(cv == null){ map.put(io,io); cv = io; } return cv; } } } String提供了自己的标准化方法,intern()方法.保留字符串的表是保留在原生内存中的,他是一个大小固定的HashTable,在Java 7u40之前默认是1009个桶,之后的版本中,默认改为60013个 可以通过-XX:StringTableSize=N设置,输出信息: -XX:+PrintStringTableStatistics(默认false) 对象重用的方式: 对象池和ThreadLocals,注意:被重用的对象会在堆中停留很长时间,如果有大量对象存于堆中,那用来创建新对象的空间就少了.并且会通过Eden S0 S1最终才会进入Old区,执行一次Full GC所化的时间与老年代中仍然存活的对象数量成正比,存活对象的数量甚至比堆的大小更重要. 线程池: 线程初始化成本高 JDBC池: 数据库连接初始化的成本高 EJB池: EJB初始化成本高 大数组:java要求,一个数组在分配的时候,其中的每个元素都必须初始化为某个默认初始值(null,0,false) 原生NIO缓冲区:不管缓冲区多大,分配一个直接java.nio.Buffer(即调用allocateDirector()方法返回的缓冲区) 安全相关的类: MessageDigest,Signature以及其他安全算法的实例 字符串编解码对象,大多数都是软引用 StringBuilder协助者:BigDecimal类在计算中间结果时会重用一个StringBuilder对象 随机数生成器: Random和SecureRandom类,生成这些类代价较高 从DNS查询到的名字:网络查询代价很高 ZIP编解码器:初始化开销不是特别高,但是释放成本很高,因为这些对象要依赖对象终结操作(finalization)来确保释放掉所用的原生内存. 对象池: (1)GC影响,降低GC效率 (2)同步: 对象池必然是同步 (3)限流(Throttling):对于稀缺的资源访问,线程池可以起到限流的作用.同时也意味着,超出的部分会等待资源. 线程局部变量:(1)生命周期管理 (2)基数性(Cardinality):线程局部变量通常会伴生线程数与保存的可重用对象数之间一一对应的关系.(3)不需要同步 注意: 初始化一个Random对象的开销非常大,而且持续创建这个类的实例,与再多个线程间共享一个类实例的同步瓶颈相比,性能可能更差.使用TreadLocalRandom类性能会更好. -XX:+PrintReferenceGC(默认false),可以输出调试信息 软引用的释放: (1):所引用的对象不能有其它的强引用,如果软引用是指向其所引用对象的唯一引用,而且该引用最近没有被访问过,则所引用对象会在下一次GC周期前释放. long ms = SoftRefLRUPolicyMSPerMB * AmountOfFreeMemoryInMb if(now - last_access_to_reference > ms) free the reference (2) 堆空间空闲内存的数量,例如堆空间4GB,再一次Full GC之后,堆可能被占用了50%,因此空闲堆是2GB,SoftRefLRUPolicyMSPerMB的默认值1000,意味着 过去的 2048s内没有访问到的任何软引用都会被清理. 如果4GB的堆占了75%,则过去的1024s没有访问到的软引用会被回收. log ms = 2048000;//2048*1000 if(System.currentTimeMillis()- last_access_to_reference_in_ms ms) free the reference 注意: 对于长期运行的应用,如果满足以下2个条件,可以考虑增加SoftRefLRUPolicyMSPerMB的值: (1)有很多空闲堆可用 (2)软引用会频繁访问 ,(不过情况罕见,增加软引用的策略值就是告诉JVM不到万不得已不要释放软引用) 软引用:当问题中的所引用对象会同时被几个线程使用时,考虑弱引用,否则入弱引用很可能会被GC掉,只有弱引用的对象在每个GC周期都可以回收 原生内存的使用 1.从Java8开始: -XX:NativeMemoryTracking=off|summary|detail 标志来跟踪JVM如何分配原生内存. 也可以使用-XX:+PrintNMTStatistics(默认false)启动 ,前提需要设置-XX:+UnlockDiagnosticVMOptions 2: 开启压缩指针: -XX:+UseCompressedOops(默认启用的) Ordinary object pointer tables Area Cool cold 2 is right $1800 col is 2 left $0099

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

Java基础巩固——反射

什么是反射 反射机制就是指程序运行时能够获取自身的信息。在Java中,只要给出类的名字,就可以通过反射机制来获取类的信息 哪里用的到反射机制 在jdbc中就是使用的反射来实例化对象,比如:Class.forName("com.mysql.jdbc.Driver.class").newInstance(); 框架都用到反射机制,spring,hibernate、struts都是用反射机制实现的。 反射机制的优点和缺点 为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念, 静态编译:在编译时确定类型,绑定对象,即通过。 动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多 态的应用,有以降低类之间的藕合性。 一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中. 它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功 能。 它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它 满足我们的要求。这类操作总是慢于只直接执行相同的操作。 利用反射机制能干什么 Class c=Class.forName("className");注明:className必须为全名,也就是得包含包名,比如,cn.netjava.pojo.UserInfo; Object obj=c.newInstance();//创建对象的实例 获取构造器 Constructor getConstructor(Class[] params)//根据指定参数获得public构造器 Constructor[] getConstructors()//获得public的所有构造器 Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器 Constructor[] getDeclaredConstructors()//获得public的所有构造器 获取类的方法 Method getMethod(String name, Class[] params),根据方法名,参数类型获得方法 Method[] getMethods()//获得所有的public方法 Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法 Method[] getDeclaredMethods()//获得所以的public和非public方法 获取类的属性 Field getField(String name)//根据变量名得到相应的public变量 Field[] getFields()//获得类中所以public的方法 Field getDeclaredField(String name)//根据方法名获得public和非public变量 Field[] getDeclaredFields()//获得类中所有的public和非public方法 使用实例 获取类属性: public class TestGetField extends Object { private static final long serialVersionUID = -2862585049955236662L; public static void main(String args[]) throws Exception { Class<?> clazz = Class.forName("reflect.TestGetField"); System.out.println("===============本类属性==============="); // 取得本类属性 Field[] fields = clazz.getDeclaredFields(); getField(fields); System.out.println("==========实现的接口或者父类的属性=========="); // 取得实现的接口或者父类的属性 Field[] fatherField = clazz.getFields(); getField(fatherField); } public static void getField(Field[] fields) { for (Field field : fields) { // 权限修饰符 int mo = field.getModifiers(); String priv = Modifier.toString(mo); Class<?> type = field.getType(); System.out.println(priv + " " + type.getName() + " " + field.getName() + ";"); } } } 获取类的方法: public class TestGetMethod implements Serializable{ private static final String testString= "hello"; public static void main(String args[]) throws Exception{ Class<?> clazz = Class.forName("reflect.TestGetMethod"); Method[] methods = clazz.getMethods(); for (Method method :methods){ Class<?> returnType = method.getReturnType(); Class<?> para[] = method.getParameterTypes(); int temp = method.getModifiers(); System.out.print(Modifier.toString(temp)); System.out.print(returnType.getName()); System.out.print(method.getName()); for (Class par:para){ System.out.println(par.getName()); } } } } 实例化类: public class TestNewInstance { public static void main(String[] args) throws Exception{ Class<?> class1 = null; class1 = Class.forName("reflect.User"); // 第一种方法,实例化默认构造方法,调用set赋值 User user = (User)class1.newInstance(); user.setAge(20); user.setName("adf"); System.out.println(user); // 第二种 取得全部的构造函数 使用构造函数赋值 } } class User { private int age; private String name; public User() { super(); } public User(String name) { super(); this.name = name; } public User(int age, String name) { super(); this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User [age=" + age + ", name=" + name + "]"; } } 使用类的方法: public class TestUseMethod { public static void main(String[] args)throws Exception{ Class<?> clazz = Class.forName("reflect.TestUseMethod"); // 调用reflect1方法 Method method = clazz.getMethod("reflect1"); method.invoke(clazz.newInstance()); // 调用reflect2方法 method = clazz.getMethod("reflect2", int.class, String.class); method.invoke(clazz.newInstance(),20,"test"); } public void reflect1() { System.out.println("Java 反射机制 - 调用某个类的方法1."); } public void reflect2(int age, String name) { System.out.println("Java 反射机制 - 调用某个类的方法2."); System.out.println("age -> " + age + ". name -> " + name); } } 动态代理: public class TestProxy { public static void main(String args[]) throws Exception{ MyInvocationHandler demo = new MyInvocationHandler(); Subject subject = (Subject) demo.bind(new RealSubject()); System.out.println(subject.say("janti",20)); } } interface Subject{ public String say(String name, int age); } // 定义真实项目 class RealSubject implements Subject { public String say(String name, int age) { return name + " " + age; } } //如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。 class MyInvocationHandler implements InvocationHandler{ private Object object = null; public Object bind(Object obj){ this.object = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object temp = method.invoke(this.object,args); return temp; } } 个人博客网站 http://www.janti.cn

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

QTQuick控件基础(2)

import QtQuick 2.2import QtQuick.Controls 1.2import QtQuick.Window 2.1ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") menuBar: MenuBar{ Menu{ title: qsTr("File") MenuItem{ text: qsTr("EXIT") onTriggered: Qt.quit() } } } Column{ spacing: 10 //button Button{ x:10;y:10;width: 140 text:qsTr("Button with menu") menu:Menu{ MenuItem{text:qsTr("Item1")} MenuItem{text:qsTr("Item2")} } } //radiobutton ExclusiveGroup{id:group} RadioButton{ text:qsTr("from top") exclusiveGroup: group checked: true } RadioButton{ text:qsTr("from cursor") exclusiveGroup: group } //switch Switch{checked: true} Switch{checked: false} //combobox ComboBox{ id:editableCombo editable: true model: ListModel{ id:model ListElement{ text:"Banana";color:"Yellow"} ListElement{ text:"Apple";color:"Green"} ListElement{ text:"Cocont";color:"Brown"} } onAccepted: { if(editableCombo.find(currentText) === -1){ model.append({text:editText}) currentIndex = editableCombo.find(editText) } } } //spinbox SpinBox{ minimumValue: -5;maximumValue: 10 prefix: "today";suffix: "degree" decimals: 1;stepSize: 1 } //TextField TextField{ width: 200 placeholderText: "写字写字" echoMode: TextInput.PasswordEchoOnEdit } TextField{width: 200} //TextArea TextArea{ width: 240 textFormat: TextEdit.RichText font.pointSize: 13 text: "<b>Hello</b><i>world!</i>" } TextArea{ width: 240 textFormat: TextEdit.PlainText font.pointSize: 13 text: "<b>Hello</b><i>world!</i>" } //BusyIndicator BusyIndicator{ running: true } //ProgressBar ProgressBar{ id:progressBar minimumValue: 0 maximumValue: 100 } Timer{ interval: 100 running: true repeat: true onTriggered: progressBar.value++ } }} 同样的道理,它在android上也有很好的实现 来自为知笔记(Wiz) 附件列表 目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com

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

QTQuick控件基础(1)

一、Item QtQuick所有的可视项目都继承自Item,它定义了可视化项目所有通用特性(x\y\width\height\anchors等)具体包括 1、作为容器 2、不透明性 没有设置opacity属性 设置了opacity属性为0.5 当然也可以这样写 3、visible属性用来设置项目是否可见。如果visible属性为false,则不接受鼠标键盘事件;同理还有enable属性; 4、堆叠顺序,简单的说,就是z越大,越在顶层。当然前提是要保证是在并集的情况下。 通过z的设置,将原本在上面的蓝色矩形变换到底层,同时将两个矩形的结构由嵌套改编成并行。 或者可以通过将z设置为负值直接达到这个目标 5、定位子项目和坐标映射 包含childAt来返回在点x,y处的子项目,以及item的mapFromItem返回item坐标系统中点映射在该项目坐标系统的结果。 二、Rectangle Rectangle主要是使用纯色或者渐变填充一个矩形区域,并提供一个边框。 1、渐变,使用了GradientStop表明渐变的头和尾 2、边框,我们实现一个圆角矩形 三、Text 可以按照常用的方式,也可以以html的方式 1、颜色,有两种表示颜色的方法 2、文本裁剪,如果clip为true则裁剪,否则通过设置文本换行或者文本省略。这个截图已经可以说明 3、超链接 四、TextInput TextInput用来显示单行可编辑纯文本。以及相关的现实策略。比如intvalidator/DoubleValidator以及RegExpoValidator等 按下回车后读取数据 当然我们推荐使用qtcontrols中的textbox 四、定位器 column/row/grid/flow是四种定位器 五、repeater和positioner用来创建大量的项目并且获得特定的数据 注意其中的index是直接委托获得的。 六、anchor锚定位 一般来说,锚都是相对于父控件的,所以记录这幅图最为重要: 七、MouseArea 其最为重要的是 onClicked事件 八、timer 实时获得当前时间 来自为知笔记(Wiz) 目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com

资源下载

更多资源
腾讯云软件源

腾讯云软件源

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

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

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

用户登录
用户注册