首页 文章 精选 留言 我的

精选列表

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

Python基础系列-闭包

版权声明:如需转载,请注明转载地址。 https://blog.csdn.net/oJohnny123/article/details/81979656 第一次调用line_conf 外部函数return的是内部函数line的内存地址,也就是line1。第二次line1(5),才是执行的内部函数line,并return了a*x+b的值,此时内部函数是可以用到之前我们传入的变量a和b的,第二次line1(5)传入的变量是x 。 这里有个知识点,就是python的内存机制,它是将一个变量的值放在内存,然后变量名引用这个值的地址。所以两个变量的值相同,可能引用的是同个内存地址噢。 区别在哪呢: 1、普通的函数都是我们传变量进去,执行并返回,引用释放,内存清掉。 2、闭包是将变量绑定给内部函数,然后返回一个内部函数的内存引用。等到我们二次执行该闭包函数的内部函数后,内存才会释放。 #!/usr/bin/python # -*- coding: UTF-8 -*- """ Created by liaoyangyang1 on 2018/8/23 下午1:41. """ #装饰器也是一种闭包 #闭包函数的实例 def line_conf(a, b): def line(x): return a*x + b return line line1 = line_conf(1, 1) print(line1(5))

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

Java基础之SPI机制

欢迎访问陈同学博客原文 在前几天的译文 Java中的类加载器 中有部分关于ContextClassLoader的内容,涉及到SPI机制,本文将学习下相关知识。 什么是SPI? SPI全称为 Service Provider Interface,直译为 服务提供者接口,翻译成中文后比较拗口,难以理解。 简单来说,SPI通过将服务的接口与实现分离以实现解耦,提高程序拓展性的机制,达到插拔式的效果。相同的标准,各服务厂商可以提供不同的实现。这尤其适合于面对未知的实现或者对拓展开放的系统,可以先行制定标准,服务提供者根据标准提供实现即可。 Java中使用SPI机制的例子很多,例举几个: 数据库驱动 ( java.sql.Driver ),各数据库厂商(Mysql、Oracle等)可以遵守规范独立开发自己的驱动 Servlet容器初始化接口( javax.servlet.ServletContainerInitializer ),Tomcat提供了实现 Apache common-logging 中提供的日志接口,许多日志框架做了实现 稍微延伸一下,其实不仅仅是Java,像计算机行业的各种规范、协议也是类似的。甚至生活中的例子,如: 命题作文:设立标题,大家各自发挥成文 手机壳:根据手机尺寸标准,实现各式各样的手机壳 喜剧:以逗笑观众为标准,各表演者以不同的作品与形式为观众送去欢乐 扯的有点远,下面以一个简单例子演示下。 SPI HelloWorld 首先,了解下SPI机制的约定(约定优于配置理念): 在 META-INF/services/ 目录下创建一个以 接口全限定名 命名的文件,文件内容为 实现类的全限定名 使用 java.util.ServiceLoader 来动态加载 META-INF/services/ 下的实现类 实现类必须有一个无参构造器 假设森林动物园举行歌唱比赛,各参赛动物选手需高歌一曲。我们定义一个接口 Animal,标准为 sing() 唱歌。 创建一个普通maven项目,创建以下对象。 // Animal接口, 制定了 sing() 标准 public interface Animal { void sing(); } 三位参赛选手,分别实现了sing() 标准 Cat.java public class Cat implements Animal { public void sing() { System.out.println("喵~"); } } Cuckoo.java public class Cuckoo implements Animal { public void sing() { System.out.println("布谷~"); } } Dog.java public class Dog implements Animal { public void sing() { System.out.println("汪~"); } } 在resource下创建META-INF/services目录,下面创建以接口全限定名org.utopiavip.spi.Animal命名的文件,内容为三位实现者: org.utopiavip.spi.Cat org.utopiavip.spi.Dog org.utopiavip.spi.Cuckoo 将项目打成jar包。 在另一个项目中引入该jar包,测试类如下: public class SpiDemo { public ServiceLoader<Animal> serviceLoader = ServiceLoader.load(Animal.class); public static void main(String args[]) { SpiDemo spiDemo = new SpiDemo(); spiDemo.sing(); } public void sing() { for (Animal singer : serviceLoader) { singer.sing(); } } } 运行后输出如下: 喵~ 汪~ 布谷~ 小例子就完成了。 Mysql驱动Demo Mysql驱动包中对 java.sql.Driver 的实现类为 com.mysql.fabric.jdbc.FabricMySQLDriver 再看看接口和实现类的ClassLoader。 System.out.println(java.sql.Driver.class.getClassLoader()); System.out.println(com.mysql.fabric.jdbc.FabricMySQLDriver.class.getClassLoader()); 输出结果如下: null sun.misc.Launcher$AppClassLoader@135fbaa4 null表示Bootstrap class loader(SPI的接口都由Bootstrap class loader加载),而实现类是由AppClassLoader加载的。 ContextClassLoader 类加载规则中有这么一点:一个类中所关联的其他类都由当前类的加载器进行加载。 仍然以Driver为例,Java中使用DriverManager来获取JDBC连接,DriverManager 位于 rt.jar 中,由Bootstrap class loader负责加载。 java.sql.DriverManager.getConnection("url", "user", "pwd") 在getConnection()的调用过程中,需要加载 java.sql.Driver 的实现类 com.mysql.fabric.jdbc.FabricMySQLDriver,可Bootstrap class loader无法找到该实现类,因为FabricMySQLDriver由System class loader加载。 这是由于类加载的委派原则及可见性制约,Bootstrap class loader将无法获取子加载器System class loader中加载的FabricMySQLDriver类。 为了解决这个问题,提出了 ContextClassLoader 概念,绕开委派原则,既然当前的加载器是Bootstrap class loader,导致无法加载FabricMySQLDriver类,那就变更当前的class loader,想加载谁就加载谁!虽然有点流氓派头,但确实是这么干的。规则是人定的,变更规则成本太高,就搞点特殊化。 java.lang.Thread 有个NB的方法 setContextClassLoader(),用来变更当前线程的class loader。 public void setContextClassLoader(ClassLoader cl) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new RuntimePermission("setContextClassLoader")); } contextClassLoader = cl; } contextClassLoader 取名也很有趣,当前线程的 context ClassLoader。特殊化也就搞一小会,不大范围搞。 /* The context ClassLoader for this thread */ private ClassLoader contextClassLoader; 小结 BB这么多,SPI其实非常简单:大佬们定规矩(规范),兄弟们实现后放到约定的地方(META-INF/service/),包装上写好是啥东西(接口全限定名),包装里写清楚东西放哪儿了(实现类全限定名)。 欢迎关注陈同学的公众号,一起学习,一起成长

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

Python基础系列-异步IO

版权声明:如需转载,请注明转载地址。 https://blog.csdn.net/oJohnny123/article/details/81980259 涉及到几个概念: 1、协程是为了解决高并发用的东西。 2、协程的优点:无需线程上下文切换的开销,由此可以提高性能。无需原子操作锁定及同步的开销。也就是说,开销小。 asyncio就是一种异步IO 协程 import threading import asyncio import requests # 把 generator 标记为 coroutine 类型,便于执行 EventLoop @asyncio.coroutine def func(port): result = requests.get('http://10.0.53.129:{0}'.format(port)) print('Start %s! code: %s (%s)' % (port,result.status_code, threading.currentThread())) # 获取 EventLoop loop = asyncio.get_event_loop() tasks = [] for i in range(8000,9000): tasks.append(func(i)) # 执行 coroutine loop.run_until_complete(asyncio.wait(tasks)) loop.close()

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

Java 基础 之 while 循环

http://www.verejava.com/?id=16992618818220 /* while 循环 while(表达式){} 如果表达式为true 继续执行,否则退出循环 */ public class Test1 { /** * @param args the command line arguments */ public static void main(String[] args) { // 输出 1 - 5 之间(包括 1,5 本身)的数. int n=1; while(n<=5) // while 判断条件true 执行循环代码, 否则终止循环 { System.out.println(n); n++; } } } http://www.verejava.com/?id=16992618818220

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

Java 基础 之 分支语句

http://www.verejava.com/?id=16992614948219 import java.util.Scanner; public class Statement2 { public static void main(String[] args) { //分支语句 //定义一个按键码变量 Scanner in=new Scanner(System.in); System.out.println("请输入按键码..."); //int keyCode=in.nextInt(); //float keyCode=in.nextFloat(); //long keyCode=in.nextLong(); //boolean keyCode=true; //byte keyCode=(byte)in.nextInt(); //short keyCode=(short)in.nextInt(); //char keyCode=(char)in.nextInt(); switch(keyCode) { case 0: System.out.println("飞机向上移动"); break; case 1: System.out.println("飞机向下移动"); break; case 2: System.out.println("飞机向左移动"); break; case 3: System.out.println("飞机向右移动"); break; default: System.out.println("飞机不移动"); break; } /* 注意: 1. default: 是当没有任何匹配条件的时候默认自动执行 2. break:表示终止switch下面的判断语句执行, 如果没有break语句程序会继续往下执行 3. switch(表达式) 表达式只能是 byte,short,int,char类型常量 */ } } http://www.verejava.com/?id=16992614948219

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

Java 基础 之 条件语句

http://www.verejava.com/?id=16992610131518 /* 流程控制语句分为 1. 条件语句 2. 分支语句 3. 循环语句 */ import java.util.Scanner; public class Statement { public static void main(String[] args) { //1.条件语句 /* 包括: 1. if(表达式){语句} 2. if(表达式){语句}else{语句} 3. if(表达式){语句}else if{语句} */ Scanner in=new Scanner(System.in); System.out.println("请输入您的考试成绩..."); int score=in.nextInt(); if(score>=90) { System.out.println("奖励一朵红花"); } else if(score>=60&&score<90) { System.out.println("没有奖励,只有鼓励,革命尚为成功,同志继续努力"); } else if(score<60) { System.out.println("挨打"); } } } /* 如果在判断条件很多的时候if{}else{} 显得有点臃肿和难读, 这样的情况下我们一般选择 分支语句 switch(表达式){} */ http://www.verejava.com/?id=16992610131518

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

Java 基础 之 位运算

http://www.verejava.com/?id=16992602784016 public class Operation5 { public static void main(String[] args) { //位运算 /* 包括: 与 &, 或 |, 取反 ~, 异或 ^ 带符号左移<<, 带符号右移 >>, 无符号右移 >>> 1. & 就是二进制位如果都是1则为1,否则为0 2. | 就是二进制位如果都是0则为0,否则为1 3. ~ 就是二进制位如果是0取反变成1,否则如果是1取反变成0; 4. ^ 就是运算两边二进制位两边同时相等时为0,否则为1 5. <<就是将二进制位逐位向左移动n位,后面补n个0,相当于乘2; 6. >>就是将二进制位逐位向右移动n位,前面补n个符号位,向当于除2; 6. >>>就是将二进制位逐位向右移动n位,前面补n个0 */ byte a=1; //二进制 00000001 byte b=8; //二进制 00001000 byte c=127; //二进制 01111111 byte d=-127;//二进制 10000001 System.out.println(a&b); //结果 00000000 System.out.println(a|b); //结果 00001001 2^3+2^0=9 System.out.println(~a); //结果 11111110补码 转换为原码=10000001=-1-1=-2 System.out.println(a^b); //结果 00001001 =9; System.out.println(a<<1); //结果 00000010 2^1=2 System.out.println(c<<1); //结果 11111110 =254 System.out.println(a>>1); //结果 00000000 =0 System.out.println(c>>1); //结果 00111111 =63 System.out.println(d>>1); //结果 11000000补码 原码=10111111=-63-1=-64 System.out.println(d>>>1);//结果 01000000原码 /* 注意: 1.计算机存储时 二进制第一位是表示符号位 1 代表负数, 0代表正数 2.计算机存储时以补码的方式存储的, 正数的补码跟原码一样,负数的补码是去掉第一位符号位取反然计算结果后 再 + 1 得到的. 3. 那补码转换成原码就反过来 去掉第一位取反计算结果后 再-1. 4. System.out.println 没有 System.out.println(byte b)方法,计算机先自动将byte转化成 int 然后在移动 */ } } http://www.verejava.com/?id=16992602784016

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

Java 基础 之 入门HelloWorld

http://www.verejava.com/?id=1699251664916 import java.lang.*; /** @author : 胡杨 @version : 1.0 1. //双斜杠代表注释, 是给人看的, 机器忽略不计 2. public 公有的, 是java 的关键字 3. class 叫 类, 每一个java文件里必须包含一个类 4. HelloWord 叫 类名, 类名可以跟文件名不一样, 但是规范一般写成一样 5. static 叫 静态的, main方法必须写static java 虚拟机才能找到 6. void 空 也就是没有返回值 7. main 叫主方法, 是java程序的入口, 必须这么写固定的, 否则程序不能运行. 8. String 字符串 是用双引号括起来的数字字符的一连串的组合 9. String[] 字符串数组 10. args 叫 main 方法的参数 11. System: 系统, out : 输出 println : 打印 12. 类名 后面{}部分叫做 类体 括号必须成对出现 13. 主方法main 后面 {} 部分叫做方法体 括号必须成对出现 14. import java.lang.*; 叫做 导入 java.lang下面的所有类, 但是java 默认 java.lang 下面的类已经导入, 所有 java.lang这个包也是java唯一可以省略不用导入的包. 编码规范: 1. 类名 第一个单词首字母大写, 如果有多个单词组成, 每个单词的首字母大写 2. java 是区分大小写的语言 3. 书写类体时{} 括号要成对出现 4. 书写方法体时{}括号要成对出现 5. 方法写在类体中 每个方法前面留一个 Tab 键空格 6. 方法中的执行语句 写作方法体中 每条执行语句 相对于方法前面留一个Tab 键空格, 并且每条执行语句后面都要写一个分号; 表示该条语句执行结束 */ public class HelloWorld { public static void main(String[] args) { //向控制台打印输出 Hello Word信息 然后换一行 System.out.println("Hello Word"); //向控制台打印输入信息, 但不换行 System.out.print("aaaa\t"); System.out.print("bbb"); } } http://www.verejava.com/?id=1699251664916

资源下载

更多资源
Mario

Mario

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

腾讯云软件源

腾讯云软件源

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

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等操作系统。

用户登录
用户注册