计算系数 给定一个多项式(ax+by)k,请求出多项式展开后xnym项的系数。
输入格式 共一行,包含 5 个整数,分别为 a,b,k,n,m,每两个整数之间用一个空格隔开。
输出格式 输出共 1 行,包含一个整数,表示所求的系数,这个系数可能很大,输出对10007 取模后的结果。
数据范围 0≤n,m≤k≤1000,
n+m=k,
0≤a,b≤106
输入样例: 1 1 3 1 2
输出样例: 3
算法分析 考察组合数的问题xnym 的系数是 Ckn anbm.Ckn=k! / n! *(k-n)!.
代码实现 #include <iostream> #include <algorithm> using namespace std; const int mod = 10007; int qmi(int a, int k) { a %= mod; int res = 1; while (k) { if (k & 1) res = res * a % mod; a = a * a % mod; k >>= 1; } return res; } int main() { int a, b, k, n, m; cin >> a >> b >> k >> n >> m; int res = qmi(a, n) * qmi(b, m) % mod;//每一项都有a,b for (int i = 1, j = k; i <= n; i ++, j -- )//计算组合数 { res = res * j % mod; res = res * qmi(i, mod - 2) % mod;//逆元相当于除法 } cout << res << endl; return 0; }
缺少某种权限
在AndroidManifest中添加权限之后仍报错
Caused by: java.lang.SecurityException: getLine1NumberForDisplay: Neither user 10289 nor current process has android.permission.READ_PHONE_STATE, android.permission.READ_SMS, or android.permission.READ_PHONE_NUMBERS
错误详情不变
选择动态添加权限
public void requestAllPower() { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS, Manifest.permission.READ_PHONE_NUMBERS, Manifest.permission.READ_PHONE_STATE}, 1); }
十二:视图
为什么要使用视图?什么是视图?
为了提高复杂SQL语句的复用性和表操作的安全性,MySQL数据库管理系统提供了视图特性。所谓视图,本质上是一种虚拟表,在物理上是不存在的,其内容与真实的表相似,包含一系列带有名称的列和行数据。但是,视图并不在数据库中以储存的数据值形式存在。行和列数据来自定义视图的查询所引用基本表,并且在具体引用视图时动态生成。
视图使开发者只关心感兴趣的某些特定数据和所负责的特定任务,只能看到视图中所定义的数据,而不是视图所引用表中的数据,从而提高了数据库中数据的安全性。视图有哪些特点?
视图的特点如下:
1)视图的列可以来自不同的表,是表的抽象和在逻辑意义上建立的新关系。
2)视图是由基本表(实表)产生的表(虚表)。
3)视图的建立和删除不影响基本表。
4)对视图内容的更新(添加,删除和修改)直接影响基本表。
5)当视图来自多个基本表时,不允许添加和删除数据。
视图的操作包括创建视图,查看视图,删除视图和修改视图。视图的使用场景有哪些?
视图根本用途:简化sql查询,提高开发效率。如果说还有另外一个用途那就是兼容老的表结构。
下面是视图的常见使用场景:
1)重用SQL语句;
2)简化复杂的SQL操作。在编写查询后,可以方便的重用它而不必知道它的基本查询细节;
3)使用表的组成部分而不是整个表;
4)保护数据。可以给用户授予表的特定部分的访问权限而不是整个表的访问权限;
5)更改数据格式和表示。视图可返回与底层表的表示和格式不同的数据。视图的优点
1)查询简单化。视图能简化用户的操作
2)数据安全性。视图使用户能以多种角度看待同一数据,能够对机密数据提供安全保护
3)逻辑数据独立性。视图对重构数据库提供了一定程度的逻辑独立性视图的缺点
1)性能:数据库必须把视图的查询转化成对基本表的查询,如果这个视图是由一个复杂的多表查询所定义,那么,即使是视图的一个简单查询,数据库也把它变成一个复杂的结合体,需要花费一定的时间。
2)修改限制:当用户试图修改视图的某些行时,数据库必须把它转化为对基本表的某些行的修改。事实上,当从视图中插入或者删除时,情况也是这样。对于简单视图来说,这是很方便的,但是,对于比较复杂的视图,可能是不可修改的
这些视图有如下特征:
1)有UNIQUE等集合操作符的视图。
2)有GROUP BY子句的视图。
3)有诸如AVG\SUM\MAX等聚合函数的视图。
4)使用DISTINCT关键字的视图。
5)连接表的视图(其中有些例外)
十三:什么是游标?
游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字。用户可以通过游标逐一获取记录并赋给主变量,交由主语言进一步处理。 十四:存储过程与函数
什么是存储过程?有哪些优缺点?
存储过程是一个预编译的SQL语句,优点是允许模块化的设计,就是说只需要创建一次,以后在该程序中就可以调用多次。如果某次操作需要执行多次SQL,使用存储过程比单纯SQL语句执行要快。优点
1)存储过程是预编译过的,执行效率高。
2)存储过程的代码直接存放于数据库中,通过存储过程名直接调用,减少网络通讯。
3)安全性高,执行存储过程需要有一定权限的用户。
4)存储过程可以重复使用,减少数据库开发人员的工作量。缺点
1)调试麻烦,但是用 PL/SQL Developer 调试很方便!弥补这个缺点。
2)移植问题,数据库端代码当然是与数据库相关的。但是如果是做工程型项目,基本不存在移植问题。
3)重新编译问题,因为后端代码是运行前编译的,如果带有引用关系的对象发生改变时,受影响的存储过程、包将需要重新编译(不过也可以设置成运行时刻自动编译)。
4)如果在一个程序系统中大量的使用存储过程,到程序交付使用的时候随着用户需求的增加会导致数据结构的变化,接着就是系统的相关问题了,最后如果用户想维护该系统可以说是很难很难、而且代价是空前的,维护起来更麻烦。
1.Linux PC:
1.1 uname -a 命令
$ uname -a Linux tssh-QiTianM415-N000 4.15.0-133-generic #137~16.04.1-Ubuntu SMP Fri Jan 15 02:55:18 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux 1.2 arch命令
$ arch x86_64 上述PC是X86架构
2.Android Phone:
$ adb shell cat /proc/cpuinfo Processor : AArch64 Processor rev 4 (aarch64) 上述Phone是aarch即ARM架构
1、遍历 foreach foreach(f: (A) => Unit): Unit
scala> val a = List(1,2,3,4) val a: List[Int] = List(1, 2, 3, 4) scala> a.foreach((x:Int) => {println(x)}) 1 2 3 4 scala> a.foreach((x:Int) => println(x)) --类型推断,不需要指定 1 2 3 4 scala> a.foreach(x => println(x)) --类型推断,不需要指定 1 2 3 4 scala> a.foreach(println(_)) --下划线简化函数定义(参数在函数体中只出现一次的情况,且函数体内没有嵌套调用时可使用) 1 2 3 4 2、映射 map def map[B](f: (A) => B): TraversableOnce[B]
通过一个函数处理后返回指定泛型(B)的新集合
scala> val a = List(1,2,3,4) val a: List[Int] = List(1, 2, 3, 4) scala> a.
本文引用 : https://yinwj.blog.csdn.net/article/details/49453303
1. 概述 经过了详细的信息格式、网络IO模型的讲解,并且通过JAVA RMI的讲解进行了预热。从这篇文章开始我们将进入这个系列博文的另一个重点知识体系的讲解:RPC。在后续的几篇文章中,我们首先讲解RPC的基本概念,一个具体的RPC实现会有哪些基本要素构成,然后我们详细介绍一款典型的RPC框架:Apache Thrift。
2. PRC概述 2.1 什么是RPC RPC(Remote Procedure Call Protocol)远程过程调用协议。一个通俗的描述是:客户端在不知道调用细节的情况下,调用存在于远程计算机上的某个对象,就像调用本地应用程序中的对象一样。比较正式的描述是:一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。那么我们至少从这样的描述中挖掘出几个要点:
RPC是协议:既然是协议就只是一套规范,那么就需要有人遵循这套规范来进行实现。目前典型的RPC实现包括:Dubbo、Thrift、GRPC、Hetty等。这里要说明一下,目前技术的发展趋势来看,实现了RPC协议的应用工具往往都会附加其他重要功能,例如Dubbo还包括了服务管理、访问权限管理等功能。网络协议和网络IO模型对其透明:既然RPC的客户端认为自己是在调用本地对象。那么传输层使用的是TCP/UDP还是HTTP协议,又或者是一些其他的网络协议它就不需要关心了。既然网络协议对其透明,那么调用过程中,使用的是哪一种网络IO模型调用者也不需要关心。信息格式对其透明:我们知道在本地应用程序中,对于某个对象的调用需要传递一些参数,并且会返回一个调用结果。至于被调用的对象内部是如何使用这些参数,并计算出处理结果的,调用方是不需要关心的。那么对于远程调用来说,这些参数会以某种信息格式传递给网络上的另外一台计算机,这个信息格式是怎样构成的,调用方是不需要关心的。应该有跨语言能力:为什么这样说呢?因为调用方实际上也不清楚远程服务器的应用程序是使用什么语言运行的。那么对于调用方来说,无论服务器方使用的是什么语言,本次调用都应该成功,并且返回值也应该按照调用方程序语言所能理解的形式进行描述。 那么上面的描述情况可以用下图表示:
2.2 RPC要素 当然,上图是作为RPC的调用者所观察到的现象(而实际情况是客户端或多或少的还是需要知道一些调用RPC的细节)。但是我们是要讲解RPC的基本概念,所以RPC协议内部是怎么回事就要说清楚:
Client:RPC协议的调用方。就像上文所描述的那样,最理想的情况是RPC Client在完全不知道有RPC框架存在的情况下发起对远程服务的调用。但实际情况来说Client或多或少的都需要指定RPC框架的一些细节。Server:在RPC规范中,这个Server并不是提供RPC服务器IP、端口监听的模块。而是远程服务方法的具体实现(在JAVA中就是RPC服务接口的具体实现)。其中的代码是最普通的和业务相关的代码,甚至其接口实现类本身都不知道将被某一个RPC远程客户端调用。Stub/Proxy:RPC代理存在于客户端,因为要实现客户端对RPC框架“透明”调用,那么客户端不可能自行去管理消息格式、不可能自己去管理网络传输协议,也不可能自己去判断调用过程是否有异常。这一切工作在客户端都是交给RPC框架中的“代理”层来处理的。Message Protocol:在上文我们已经说到,一次完整的client-server的交互肯定是携带某种两端都能识别的,共同约定的消息格式。RPC的消息管理层专门对网络传输所承载的消息信息进行编号和解码操作。**目前流行的技术趋势是不同的RPC实现,为了加强自身框架的效率都有一套(或者几套)私有的消息格式。**例如前文所讲到的RMI框架使用的消息协议为JRMP;后文我们将详细讲解的RPC框架Thrift也有私有的消息协议,“- Transfer/Network Protocol”(当然它还支持一些通用的消息格式,如JSON)。Transfer/Network Protocol:传输协议层负责管理RPC框架所使用的网络协议、网络IO模型。例如Hessian的传输协议基于HTTP(应用层协议);而Thrift的传输协议基于TCP(传输层协议)。传输层还需要统一RPC客户端和RPC服务端所使用的IO模型;Selector/Processor:存在于RPC服务端,由于服务器端某一个RPC接口的实现的特性(它并不知道自己是一个将要被RPC提供给第三方系统调用的服务)。所以在RPC框架中应该有一种“负责执行RPC接口实现”的角色。它负责了包括:管理RPC接口的注册、判断客户端的请求权限、控制接口实现类的执行在内的各种工作。IDL:实际上IDL(接口定义语言)并不是RPC实现中所必须的。但是需要跨语言的RPC框架一定会有IDL部分的存在。这是因为要找到一个各种语言能够理解的消息结构、接口定义的描述形式。如果您的RPC实现没有考虑跨语言性,那么IDL部分就不需要包括,例如JAVA RMI因为就是为了在JAVA语言间进行使用,所以JAVA RMI就没有相应的IDL。 一定要说明一点,不同的RPC框架实现都有一定设计差异。例如生成Stub的方式不一样,IDL描述语言不一样、服务注册的管理方式不一样、运行服务实现的方式不一样、采用的消息格式封装不一样、采用的网络协议不一样。但是基本的思路都是一样的,上图中的所列出的要素也都是具有的。
2.3 典型的RPC框架介绍 JAVA RMI:是不是觉得前文中我们介绍RMI所提到几个关键概念在RPC中都找得到一些影子。是的,RPC最早就是由SUN提出,并在后来由IETF ONC修订。RMI就是一个典型的RPC实现,只不过RMI不支持跨语言性,所以RMI中也没有IDL存在的必要。但是RMI真心快,并且由于没有IDL的存在,在构建一套完整的RPC实现时要比其他RPC框架少了一些步骤,所以使用起来也比较简单。如果您的业务需求中并不存在跨语言的考虑,并且基本上主要系统都是用JAVA实现,那么RMI绝对是您一个可以考虑的方案。GRPC:GRPC是一个高性能、通用的开源RPC框架,由Google主要面向移动应用开发并基于HTTP/2协议(注意是HTTP/2协议,不是我们常使用的HTTP 1_1。HTTP/2协议详细的介绍可以参见官方地址:https://http2.github.io/)标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。为了支持GRPC的跨语言性,GRPC有一套独立存在IDL语言。不过由于GRPC是Google的开源产品,在信息格式封装方面Google主要还是推广的自己的ProtoBuf,所以GPRC是不支持其他信息格式的(至少ProtoBuf效率是大家有目共睹的)。关于GRPC详细的使用介绍,可以参见官方地址:https://github.com/grpc/grpcThrift:Thrift是Facebook的一个开源项目,后来进入Apache进行孵化。Thrift也是支持跨语言的,所以它有自己的一套IDL。目前它支持几乎所有主流的编程语言:C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages。Thrift可以支持多种信息格式,除了Thrift私有的二进制编码规则和一种LVQ(类似于TLV消息格式)的消息格式,还有常规的JSON格式。Thrift的网络协议建立在TCP协议基础上,并且支持阻塞式IO模型和多路IO复用模型。我们将在后文详细讲解Apache Thrift的使用。Thrift也是目前最流行的RPC框架之一,从网络上各种性能测试情况开,Thrift的性能都是领先的。Thrift的官网地址为:http://thrift.apache.org/Hetty:Hetty是一款构建于Netty和Hessian基础上的高性能的RPC框架。Hetty的网络协议基于HTTP,由于采用了Netty,所以Hetty支持阻塞式IO模型和多路IO复用模型。Hetty的消息格式采用私有的二进制流格式。其他的RPC框架:除了上诉的RPC协议的实现外,还有:Wildfly、Hprose等等。Hprose是一款国人主导的RPC实现,感兴趣的读者可以去看看(http://www.hprose.com/)。另外基于RPC的定义,Xfire,CXF这些Web Service框架也属于RPC:WSDL描述文件就是他们的IDL,通过WSDL为不同的编程语言生成Stub、通过不同的Web服务器管理具体服务实现的运行过程、HTTP是它们的通信协议、XML是它们的消息格式。 3. RPC框架的性能依据 在物理服务器性能相同的情况下,以下几个因素会对一款RPC框架的性能产生直接影响:
所支持的网络IO模型:您的RPC服务器可以只支持传统的阻塞式同步IO,也可以做一些改进让您的RPC服务器支持非阻塞式同步IO,或者在您的服务器上实现对多路IO模型的支持。这样的RPC服务器的性能在高并发状态下,会有很大的差别。特别是单位处理性能下对内存、CPU资源的使用率。基于的网络协议:一般来说您可以选择让您的RPC使用应用层协议,例如HTTP或者之前我们提到的HTTP/2协议,或者使用TCP协议,让您的RPC框架工作在传输层。工作在哪一层网络上会对RPC框架的工作性能产生一定的影响,但是对RPC最终的性能影响并不大。但是至少从各种主流的RPC实现来看,没有采用UDP协议做为主要的传输协议的。选择的消息封装格式:选择或者定义一种消息格式的封装,要考虑的问题包括:消息的易读性、描述单位内容时的消息体大小、编码难度、解码难度、解决半包/粘包问题的难易度。当然如果您只是想定义一种RPC专用的消息格式,那么消息的易读性可能不是最需要考虑的。消息封装格式的设计是目前各种RPC框架性能差异的最重要原因,这就是为什么几乎所有主流的RPC框架都会设计私有的消息封装格式的原因。实现的服务处理管理方式:在高并发请求下,如何管理注册的服务也是一个性能影响点。您可以让RPC的Selector/Processor使用单个线程运行服务的具体实现(这意味着上一个客户端的请求没有处理完,下一个客户端的请求就需要等待)、您也可以为每一个RPC具体服务的实现开启一个独立的线程运行(可以一次处理多个请求,但是操作系统对于“可运行的最大线程数”是有限制的)、您也可以线程池来运行RPC具体的服务实现(目前看来,在单个服务节点的情况下,这种方式是比较好的)、您还可以通过注册代理的方式让多个服务节点来运行具体的RPC服务实现。
SuppressWarnings注解是jse提供的注解。作用是屏蔽一些无关紧要的警告。使开发者能看到一些他们真正关心的警告。从而提高开发者的效率
简介:
java.lang.SuppressWarnings是J2SE 5.0中标准的Annotation之一。可以标注在类、字段、方法、参数、构造方法,以及局部变量上。作用:告诉编译器忽略指定的警告,不用在编译完成后出现警告信息。
使用:
@SuppressWarnings(“”)
@SuppressWarnings({})
@SuppressWarnings(value={})
根据sun的官方文档描述:
value - 将由编译器在注释的元素中取消显示的警告集。允许使用重复的名称。忽略第二个和后面出现的名称。出现未被识别的警告名不是 错误:编译器必须忽略无法识别的所有警告名。但如果某个注释包含未被识别的警告名,那么编译器可以随意发出一个警告。
各编译器供应商应该将它们所支持的警告名连同注释类型一起记录。鼓励各供应商之间相互合作,确保在多个编译器中使用相同的名称。
示例:
@SuppressWarnings("unchecked")
告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。
@SuppressWarnings("serial")
如果编译器出现这样的警告信息:The serializable class WmailCalendar does not declare a static final serialVersionUID field of type long,使用这个注释将警告信息去掉。
@SuppressWarnings("deprecation")
如果使用了使用@Deprecated注释的方法,编译器将出现警告信息。使用这个注释将警告信息去掉。
@SuppressWarnings("unchecked", "deprecation")
告诉编译器同时忽略unchecked和deprecation的警告信息。
@SuppressWarnings(value={"unchecked", "deprecation"})
等同于@SuppressWarnings("unchecked", "deprecation")
@SuppressWarnings注解的作用
J2SE 提供的最后一个批注是 @SuppressWarnings。该批注的作用是给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默。
@SuppressWarnings 批注允许您选择性地取消特定代码段(即,类或方法)中的警告。其中的想法是当您看到警告时,您将调查它,如果您确定它不是问题,
您就可以添加一个 @SuppressWarnings 批注,以使您不会再看到警告。虽然它听起来似乎会屏蔽潜在的错误,但实际上它将提高代码安全性,因为它将防止
您对警告无动于衷 — 您看到的每一个警告都将值得注意。
我经常遇到的问题是不晓得什么时候用@SupressWarnings的什么批注好,所以做了如下整理
使用:
@SuppressWarnings(“”)
@SuppressWarnings({})
@SuppressWarnings(value={})
一.@SuppressWarings注解
作用:用于抑制编译器产生警告信息。
示例1——抑制单类型的警告:
@SuppressWarnings("unchecked")
public void addItems(String item){
背景:
J2SE提供的最后一个注解是@SuppressWarnings。该批注的作用是给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默。
@SuppressWarnings注解允许您选择性地取消特定代码段(即,类或方法)中的警告。其中的想法是当您看到警告时,您将调查它,如果您确定它不是问题,您就可以添加一个@SuppressWarnings注解,以使您不会再看到警告。虽然它听起来似乎会屏蔽潜在的错误,但实际上它将提高代码安全性,因为它将防止您对警告无动于衷 — 您看到的每一个警告都将值得注意。
一、@SuppressWarings注解
作用:用于抑制编译器产生警告信息。
示例1、抑制单类型的警告:
@SuppressWarnings("unchecked")public voidaddItems(String item){
@SuppressWarnings("rawtypes")
List items= newArrayList();
items.add(item);
}
示例2、抑制多类型的警告:
@SuppressWarnings(value={"unchecked", "rawtypes"})public voidaddItems(String item){
List items= newArrayList();
items.add(item);
}
示例3、抑制所有类型的警告:
@SuppressWarnings("all")public voidaddItems(String item){
List items= newArrayList();
items.add(item);
}
二、注解目标
通过@SuppressWarnings的源码可知,其注解目标为类、字段、函数、函数入参、构造函数和函数的局部变量。
而大家建议注解应声明在最接近警告发生的位置。
二、抑制警告的关键字
all to suppress all warnings (抑制所有警告)
boxing to suppress warnings relative to boxing/unboxing operations(抑制装箱、拆箱操作时候的警告)
cast to suppress warnings relative to cast operations (抑制映射相关的警告)
dep-annto suppress warnings relative to deprecated annotation(抑制启用注释的警告)
文章目录 ARP数据包分类:分类1:分类2: ARP协议工作原理: ARP数据包分类: 分类1: 1.广播包:目的MAC地址为:FF-FF-FF-FF-FF-FF,交换机设备收到广播包后,转发给局域网内所有主机。
2.非广播包:只有目的主机才接收。
分类2: 1.请求包:请求获取局域网内某IP对应的MAC地址。
2.回复包:通告别的主机自己的IP地址和MAC地址。
ARP协议工作原理: 1.每个主机都会在自己的ARP缓冲区中建立ARP列表,存储IP地址和MAC地址的对应关系。
2.当某个主机新加入网络时(也可能是MAC地址变化、接口重启),会将自己的IP地址和MAC地址广播给其他主机。
3.网络上的主机收到ARP报文时,会更新ARP缓冲区。
4.当某个主机需要发送报文时,会检查ARP列表是否有目的主机IP地址对应的MAC地址,如果有则直接发送;如果没有则发送广播请求包,数据包内容有自己的IP地址和MAC地址,目的主机的IP地址等。
5.当其他主机收到该ARP数据包时:
如果数据包中的IP地址不是自己的,那么忽略
如果数据包中的IP地址是自己的,那么先用数据包中的源IP地址和源MAC地址更新自己的ARP列表,然后发送一个回复包,告诉源主机自己的MAC地址。
6.源主机收到回复后,更新ARP列表,然后继续发送数据。如果源主机久久收不到回复,则表示此次ARP查询失败。
内部类
构造函数
1.父类的构造函数一定会执行,并先于子类的构造函数执行。如果在调用子类的构造函数时,没有显式调用父类构造函数,则先调用父类的无参构造函数,再执行子类构造函数。如:
public class SuperClass {
public SuperClass() {
System.out.println("super.");
}
public SuperClass(String name) {
System.out.println("super with name: " + name);
}
}public class SubClass {
public SubClass() {
System.out.println("sub.");
}
public SubClass(String name) {
//A
System.out.println("sub with name: " + name);
}
}
那么执行 SubClass(String name) 时,会在//A处先执行Super(),再继续执行 SubClass(String name) 剩下的代码。
2.如果父类定义了有参构造函数,那就没有了默认无参构造函数,如果子类的构造函数里不显式调用父类自定义的构造函数,编译时就会报找不到父类无参构造函数的错。 解决这一编译错误,可以在父类定义一个无参构造函数,或者在子类调用构造函数时显式调用已定义的父类构造函数。
3.在子类的构造函数中,显式调用父类构造函数的super必须放在第一行,而且至多只能有一个super,否则编译不通过。
4.java继承中对构造函数是不继承的,只是调用(隐式或显式)。
初始化顺序
1、初始化父类静态成员(包括静态成员变量、静态代码块,按出现的先后顺序进行初始化);
2、初始化子类静态成员(包括静态成员变量、静态代码块,按出现的先后顺序进行初始化);
3、初始化父类成员变量(包括成员变量、初始代码块,按出现的先后顺序进行初始化);
4、调用父类构造函数(显式super或隐式调用);
5、初始化子类成员变量(包括成员变量、初始代码块,按出现的先后顺序进行初始化);
6、调用子类构造函数
继承
1、子类不会继承父类的构造函数,只能显式或隐式调用。
2、子类会继承父类的静态变量和静态方法,但如果该静态变量和方法被父类声明为private,则不能继承。
算法原理
BitMap的基本思想就是用一个bit位来标记某个元素对应的Value,而Key即是该元素。由于采用了Bit为单位来存储数据,因此可以大大节省存储空间。
BitMap可以看成一种数据结构。
假设有这样一个需求:在20亿个随机整数中找出某个数m是否存在其中,并假设32位操作系统,4G内存。
在Java中,int占4字节,1字节=8位(1 byte = 8 bit)。
如果每个数字用int存储,那就是20亿个int,因而占用的空间约为 (2000000000*4/1024/1024/1024)≈7.45G
如果按位存储就不一样了,20亿个数就是20亿位,占用空间约为 (2000000000/8/1024/1024/1024)≈0.233G
优点和缺点
优点:由于采用了Bit为单位来存储数据并建立映射关系来查找位置,因此可以大大减少存储空间,加快在大量数据中查询的时间。(有点哈希表的意思,但哈希中的value值数据类型可以丰富多样,而BitMap最终查到的value只能表示简单的几种状态。)
缺点:BitMap中的查询结果(value)能表达的状态有限,且所有的数据不能重复。即不可对重复的数据进行排序和查找。
算法实现(C#)
.NET中已经实现了BitMap的数据结构——BitArray,建议使用BitMap算法解决问题时直接使用官方的BitArray。
我参照.NET源码实现了一个简化版的BitMap,以int数组存储位值(最多存21亿个位值),代码如下:
class BitMap
{
public int Length{ get{ return m_length;}
}
private int[] m_array;
private int m_length;
public BitMap(int length): this(length, false) { }
//索引根据需求添加
public bool this[int index]
{
get
{
return Get(index);
}
set
{
Set(index,value);
}
}
//分配空间以容纳长度位值, 位数组中的所有值都设置为defaultValue。
public BitMap(int length, bool defaultValue)
{
if (length < 0) {
java中判断某元素是否存在数组中的方法:
1、通过将数组转换成List,然后使用List中的contains进行判断其是否存在public static boolean useList(String[] arr,String containValue){
return Arrays.asList(arr).contains(containValue);
}
需要注意的是Arrays.asList这个方法中转换的List并不是java.util.ArrayList而是java.util.Arrays.ArrayList,其中java.util.Arrays.ArrayList中不能对数组的长度进行扩容操作,这个尤为重要,其中contains实现如下:@Override
public boolean contains(Object o) {
//调用indexOf方法判断其在那个位置,判断其时候为-1
return indexOf(o) != -1;
}
@Override
public int indexOf(Object o) {
//获取元素
E[] a = this.a;
//判断空
if (o == null) {
//循环判断
for (int i = 0; i < a.length; i++)
//如果元素为null
if (a[i] == null)
//则返回
return i;
} else {
//如果其不为空
for (int i = 0; i < a.length; i++)
一、uboot启动流程简介
与大多数BootLoader一样,uboot的启动过程分为BL1和BL2两个阶段。BL1阶段通常是开发板的配置等设备初始化代码,需要依赖依赖于SoC体系结构,通常用汇编语言来实现;BL2阶段主要是对外部设备如网卡、Flash等的初始化以及uboot命令集等的自身实现,通常用C语言来实现。
1、BL1阶段
uboot的BL1阶段代码通常放在start.s文件中,用汇编语言实现,其主要代码功能如下:
(1) 指定uboot的入口。在链接脚本uboot.lds中指定uboot的入口为start.S中的_start。
(2)设置异常向量(exception vector)
(3)关闭IRQ、FIQ,设置SVC模式
(4)关闭L1 cache、设置L2 cache、关闭MMU
(5)根据OM引脚确定启动方式
(6)在SoC内部SRAM中设置栈
(7)lowlevel_init(主要初始化系统时钟、SDRAM初始化、串口初始化等)
(8)设置开发板供电锁存
(9)设置SDRAM中的栈
(10)将uboot从SD卡拷贝到SDRAM中
(11)设置并开启MMU
(12)通过对SDRAM整体使用规划,在SDRAM中合适的地方设置栈
(13)清除bss段,远跳转到start_armboot执行,BL1阶段执行完
2、BL2阶段
start_armboot函数位于lib_arm/board.c中,是C语言开始的函数,也是BL2阶段代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,BL2阶段的主要功能如下:
(1)规划uboot的内存使用
(2)遍历调用函数指针数组init_sequence中的初始化函数
(3)初始化uboot的堆管理器mem_malloc_init
(4)初始化SMDKV210开发板的SD/MMC控制器mmc_initialize
(5)环境变量重定位env_relocate
(6)将环境变量中网卡地址赋值给全局变量的开发板变量
(7)开发板硬件设备的初始化devices_init
(8)跳转表jumptable_init
(9)控制台初始化console_init_r
(10)网卡芯片初始化eth_initialize
(11)uboot进入主循环main_loop
二、uboot程序入口分析
1、link.lds链接脚本文件分析
u-boot.lds文件是uboot工程的链接脚本文件,位于board\samsung\smdkc110目录下,对于工程项目编译后期的链接阶段非常重要,决定了uboot程序的组装。
u-boot.lds链接文件中的ENTRY(_start)指定了uboot程序的入口地址为_start。
2、定位uboot程序入口地址
在SourceInsight建立uboot工程,利用索引功能查找_start,在搜索结果中找到与三星smdkv210开发板相关的代码,最终锁定cpu\s5pc11x\start.S文件,定位到文件中的_start标识符。
三、start.S文件分析
1、头文件分析
start.S有四个头文件:
#include <config.h>
config.h头文件在配置开发板时由mkconfig脚本创建的头文件,头文件内容即包含开发板的头文件:#include <configs/smdkv210single.h> #include <version.h>
version.h头文件的内容为包含自动生成的版本头文件,头文件内容为:#include "version_autogenerated.h",version_autogenerated.h头文件定义了版本宏,宏定义为:#define U_BOOT_VERSION "U-Boot 1.3.4"。版本宏的值就是Makefile中定义的版本信息。 #include <asm/proc/domain.h>
domain.h头文件在定义了CONFIG_ENABLE_MMU宏时有效,为链接文件,实际指向的文件为include/asm-arm/proc-armv/domain.h。 #include <regs.h>
regs.h头文件为链接文件,指向s5pc110.h头文件,s5pc110.h文件内部使用宏定义了有关SoC内部寄存器的大量信息。
2、头校验信息的占位
#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
.word 0x2000
.word 0x0
一、冒泡排序(稳定) 原理:通过重复的遍历未排序的数组,一次比较两个元素,如果它们顺序错误就交换,直到遍历数组没发现要交换的元素,排序就完成了。
void Swap(int& num1, int& num2) { int temp = num1; num1 = num2; num2 = temp; } void BubbleSort(int* arr, int len) { if (!arr) return; for (int i = 0; i < len - 1; i++) { bool tag = true; for (int j = 0; j < len - i - 1; j++) { if (arr[j] > arr[j + 1]) { Swap(arr[j], arr[j + 1]); tag = false; } } if (tag)break; } } 二、选择排序(不稳定) 原理:遍历数组,找出最小(大)值,放在数组首(尾),然后遍历剩下的无序的数组,重复这一步骤。
例如int型
#include<iostream> #include<cstdio> #include<climits> using namespace std; int main() { printf("%d\n",sizeof(int)); printf("%d\n",INT_MAX); printf("%d\n",INT_MIN); }; 注意要用头文件limits获取数据类型范围
以下为各数据类型界限符
有符号整数类型:
char:CHAR_MIN、CHAR_MAX
short:SHRT_MIN、SHRT_MAX
int:INT_MIN、INT_MAX
long:LONG_MIN、LONG_MAX
long long:LLONG_MIN、LLONG_MAX
无符号整数类型:
unsigned char:0、UCHAR_MAX
unsigned short:0、USHRT_MAX
unsigned int:0、UINT_MAX
unsigned long:0、ULONG_MAX
unsigned long long:0、ULLONG_MAX
浮点型类型:
float:FLT_MIN、FLT_MAX
double:DBL_MIN、DBL_MAX
long double:LDBL_MIN、LDBL_MAX
场景:整个系统的DML操作需要记录日志
记录内容:1 操作人 2 操作时间 3 操作类型(登录 新增 修改 删除) 4 操作描述 5 详细请求数据(varchar2()) 6 操作IP ==>日志表
实现:
原来方式:在每个方法的里面编写记录日志代码;
缺点:代码重复 ,与原有逻辑耦合度高。
AOP: 将日志记录功能提取到切面中。动态切入到需要日志记录的方法上即可;
优点: 解耦合,代码复用。
1) 先写一个日志切面LogAspect.java;
//日志切面
@Component//对象由spring管理
@Aspect//切面注解
public classLogAspect {//定义切入点,切入到添加了LogData注解的方法上
@Pointcut("@annotation(aop.LogData)")public voidpointCut(){}/**
* 记录日志的切面方法
* 在该方法中定义统一的日志记录逻辑
* @param joinPoint*/@Before("pointCut()")public voidlog(JoinPoint joinPoint){
System.out.println("进入日志Aspect");
}
}
2)写一个日志信息LogData.java;
//自定义日志注解
@Target({ElementType.METHOD})//指定作用的目标对象(可以添加的位置)
@Retention(RetentionPolicy.RUNTIME)//指定在运行期间起作用
public@interface LogData {//定义注解中的属性
String description() default "";//日志类型
intlogType();
}
3)在控制层方法上写上注解,加上描述信息,描述日志;
@LogData(logType = 1,description = "学生信息修改")
@RequestMapping("/update")publicString update(Integer id,ModelMap modelMap){//查询用户信息,展示到页面
创建一个cJSON cJSON * json = cJSON_CreateObject();//创建 cJSON_Delete(json);//删除 添加值 JSON的数据是以键值对的形式存在的,就这样
{key:value} 不懂的话可以把key想象为变量名,value就是变量的值,使用时用key取出value。
cJSON_Add…ToObject(cJSON变量,charkey,…)
这是通用的格式。
(话说cJSON长得好像map)
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); 这是所有的对Object添加的函数。
通常的GC算法很繁重,一旦GC开始执行,我们原本该进行的程序就被迫停止。也就是说,繁重的GC原本是辅助程序变成了主程序,而本该执行的主程序变成了辅程序。这就是臭名昭著的停止型GC,英文名称很酷叫:Stop the world GC。针对繁重的GC算法,人们提出增量式垃圾回收算法。增量:incremental,意味着慢慢变化,也就是说增量式垃圾回收算法是慢慢回收,一点一点与主程序交替执行而不是直接霸占主程序的运行时间。
三色标记算法
三色标记算法由图灵奖得主Dijkstra等人提出。三种颜色所包含的意思如下:
白色:未搜索过的对象
灰色:正在搜索的对象
黑色:搜索完成的对象
我们以标记-清除算法为例说明。GC初始所有对象都标记为白色,GC一开始由根开始遍历搜索对象,GC发现对象但还没搜索的标记为灰色,灰色对象依次从栈取出并且子对象也标记为灰色,当其所有子对象标记灰色时,他自己就标记为黑色。这里,标记为黑色的对象则表示搜索完毕,GC这一轮就不再对其搜索。GC结束时就不存在灰色对象,黑色为活动对象,白色为垃圾。这里三色的概念不仅用于标记-清除算法,也可以用于其它算法。但是这种简单处理的三色标记算法会有BUG,我们以下图为例:
当GC执行到图1的时候,这是候GC时间片结束,系统执行主程序,将图1的对象引用且换到图3的状态,此刻接着执行GC。由于A已被标记为黑色则不在对A的子对象搜索,灰色B对C的指向被取消此时B子对象搜素完毕也将标志黑色,而C本是被A指向由于没被GC发现则被当作垃圾清理。为了解决这种BUG在这里解决问题的关键也在于运用写入屏障。,一下将介绍3为科学家提出的3中解决方案。
Dijkstra Dijkstra提出在GC切换为主程序后如果新引用的对象newobj没有被标记,那么就将其标记后堆在标记栈里。也就是说,如果Newobj是白色的,那么被新引入后则标记为灰色。
结果如上图所示。这样在下一次启动GC的时候由于C是灰色也就是未完成搜索的对象,则GC就不会将C视为垃圾处理,但是这里A已经是黑色对象,所以GC也不会对C进行搜索。接下来标记-清除-分配的流程和典型的标记-分配算法没什么两样,需要注意的是停止型GC是在分块完全枯竭后才启动的,然后增量式垃圾回收是逐步推荐GC的。
缺点:这个算法中即使C之后变成了垃圾,结果垃圾对象C以及C引用的其他垃圾都会被遗留下来。
Steele steele算法中的写入屏障要比Dijkstra严格,但是他能减少错误标记的对象。steele算法在标记过程中发出引用的对象是黑色对象,且新引用的目标对象为灰色或白色,那么我们就把发出引用的对象涂为白色。
这个算法相比于Dijkstra,由于A被重新标记为灰色,那么下次启动的GC就会从根开始从A向C进行搜索,这样就弥补了Dijkstra算法的不足之处。
汤浅太一 汤浅提出的写入屏障的算法也称为“快照GC”。因为这种算法是以GC开始时对象间的引用关系为基础来执行GC的。根据汤浅的算法,在GC开始时回收垃圾,保留GC开始时的活动对象和GC执行过程中的分配对象。
汤浅的算法结果和Dijkstra结果一样,但是在第二步中过程却和Dijkstra不一样。Dijkstra在图一到图二将C标记为灰色,而汤浅的算法在图2到图3标记为灰色。而这样的顺序就能巧妙的避免标记遗漏的问题。汤浅的算法虽然简单也保留了很多对象,但是最后事实上却无意保留了很多无用的对象。
Java教程 - Java整数类型
Java字节类型
最小的整数类型为byte。byte类型变量在使用来自网络或文件的数据流时非常有用。
字节变量通过使用byte关键字声明。下面声明两个字节变量b和c:byte b, c;
byte是有符号的8位类型,范围从-128到127。
以下代码创建两个字节类型变量并分配值。public class Main {
public static void main(String[] args) {
byte b1 = 100;
byte b2 = 20;
System.out.println("Value of byte variable b1 is :" + b1);
System.out.println("Value of byte variable b1 is :" + b2);
}
}
上面的代码生成以下结果。
字节类在对象中封装了原始类型字节的值。字节类提供了将字节转换为字符串和字符串转换为字节的几种方法
Java short类型
Java short类型的大小在字节和整数之间。
short是一个有符号的16位类型。短类型变量的范围为-32,768到32,767。
下面是一些简短变量声明的例子:short s;
short t;
Java int类型
当在表达式中使用字节和短型值时,在求值表达式时将它们提升为int。
int是有符号的32位类型,范围为-2,147,483,648到2,147,483,647。
Java long类型
当int类型不够大时,使用Java long类型。
long是一个有符号的64位类型和。长型的范围是-9,223,372,036,854,775,808至9,223,372,036,854,775,807。
要指定一个长文字,你需要告诉编译器字面值的类型为long,通过在文本上附加一个大写或小写的L。例如,0x7ffffffffffffffL或123123123123L。
以下代码创建一个long类型文字,并将值分配给along类型变量。public class Main {
写Java程序时会经常从classpath下读取文件,是时候该整理一下了,并在不断深入的过程中,陆续补充上。
现在Java project 都以maven项目居多, 比如像下面这样的一个项目结构:
编译后的class文件都到了target目录,如下面的结构:
看代码:
importjava.io.File;importjava.net.URL;public classPoem {public static voidmain(String[] args) {
Poem poem= newPoem();
poem.getFile("extObj.txt");
}private voidgetFile(String fileName) {
ClassLoader classLoader=getClass().getClassLoader();/**getResource()方法会去classpath下找这个文件,获取到url resource, 得到这个资源后,调用url.getFile获取到 文件 的绝对路径*/URL url=classLoader.getResource(fileName);/*** url.getFile() 得到这个文件的绝对路径*/System.out.println(url.getFile());
File file= newFile(url.getFile());
System.out.println(file.exists());
}
}
通过上面这种方式就可以获取到这个文件资源。
在一个static method 里可以直接通过类的ClassLoader对象获取文件资源。
URL url = Poem.class.getClassLoader().getResource("extObj.txt");
File file= new File(url.getFile());
//直接获取到输入流//fileName 就是resources里的文件名
InputStream in = Poem.class.getClassLoader().getResourceAsStream(fileName);
综上述,类里的getClassLoader去寻找fileName都是从classpath去找的,毕竟是ClassLoader嘛。
如果一个包里面有一个配置文件,那该怎么获取呢? 如图:
第一个dbconfig.properties在类package下,第二个dbconfig.properties在resources目录下,
那怎么获取到package下的dbconfig properties文件呢?
here goes code:
packagecom.getfilefromclasspath;importjava.io.IOException;importjava.io.InputStream;importjava.util.Properties;public classClassLoaderDemo {public static void main(String[] args) throwsIOException {