java笔记3

git reset

reset既可以处理commit后的回退,还可以处理add后的返回

状态机设计

controller类负责对外的接口,worker类负责实际干活,这两个是没有什么疑问的。

重要的是stateMachine和各个子state的区别,statemachine正常情况下是只做命令透传给当前的子state,而不应该做状态切换,状态切换应该由各个子state去做。

但是,有的情况下,状态的切换不是由controller触发的,比如当installing进度到达100时,应该切换到installsuccess的状态,这个状态的切换就比较有意思了。应该是由installing状态返回getProcess方法进度值100,但是不做切换动作,然后由statemachine类判断进度值,statemachine也不直接切状态,而是由statemachine去触发一个installsucced的方法,交由当前的状态去响应这个方法,而installing对installsucceed方法的响应就是切状态。

只有这样,你才能保证,在installing状态能自发切installsuccess状态,且能不断多次调用getProgress,同时在installsuccess状态能响应getProgress指令,同时所有的状态切换都是由子state完成。同时保证只有切状态的指令如installsucceed会触发切换状态,而子state的getProgress本身不会切换状态。

openssl命令

P7B证书:

der转pem: openssl pkcs7 -inform der -in a.p7b -out a.cer
读取证书pem里的信息: openssl pkcs7 -in 03user.p7b -print_certs -print -text
把p7b的pem的的证书链单独搞出来到单独的cert的pem里: openssl pkcs7 -inform DER -print_certs -in <path of the file> | awk 'split_after==1{n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > "cert" n ".pem"}'

ED25519加密

参考https://blog.pinterjann.is/ed25519-certificates.html

生成秘钥:openssl genpkey -algorithm ED25519 > 03.pem

手动构造一个配置文件25519cnf:

[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no
[req_distinguished_name]
C = DE
CN = www.example.com
[v3_req]
keyUsage = keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = www.example.com
DNS.2 = example.com

生成申请证书用的requset: openssl req -new -out exa.csr -key 03.pem -config 25519.cnf

查看request:openssl req -in exa.csr -text -noout

根据requset查看公钥(后面可以在crt里看公钥更好):openssl req -in exa.csr -pubkey

根据request和签发用的私钥生成证书(此处使用自签名):openssl x509 -req -days 700 -in exa.csr -signkey 03.pem -out exa.crt

读取证书信息:openssl x509 -text -in exa.crt

快速启动一个文件服务器

SimpleHTTPServer是python自带的模块,可以快速启动一个能够在网页上访问的文件服务器:

linux: python -m SimpleHTTPServer 8081

Windows: python -m http.server 8081

查看共享内存的方式

看句柄:lsof -p $(pidof com.huawei.updateagent) |grep shmem

看内存信息:dumpsys meminfo com.huawei.ivi.hmi.launcher

看文件句柄: ls -al /proc/$(pidof com.huawei.updateagent)/fd |grep ashmem

看资源限制: cat /proc/$(pidof com.huawei.updateagent)/limits

java和CPP的对比

数据类型:

长度JAVACPP
不定boolean(java中的boolean不是1个bit,而是1个或者4个字节,根据JVM的实现而不同)bool
8bytechar / signed char / unsigned char(cpp中的char是个坑,char不像short、int、long那样默认就是signed,而是根据编译器不同而不同,最好是手动制定signed或者unsigned,而且这里的char是8位的。不过字符字面量倒是既可以转化为unsigned char,也可以转化为signed char,因为ascii码只有128个)
16char(java中的char是16位,而且可以表达utf)
16shortshort / unsigned char
32intint / unsigned int
64longlong long/ long / unsigned long (cpp的long/unsigned long也是坑,是不可移植的,在不同系统可能不一样,可能是32,也可能是64, 现今一般把long long当做是64位)
32floatfloat
64doubledouble

常用接口对比

String: (cpp的命名普遍简短一点)

JAVACPP
char a = s.charAt(0)char a = s.at(0) / s[0]
String sub = s.substring(6, 11) (6是左闭,11是右开)std::string sub = s.substr(6, 5) (6是左闭,5是长度)
boolean out = s.equals(b)bool out = (s.compare(b) == 0)
其他两者一样

迭代器:

JAVACPP
Iterator<String> it = l.iterator();std::vector< std::string >::iterator& it = l.begin(); (一般直接用auto方便, 迭代器可以是引用也可以不是引用)
it.hasNext();it != l.end();
String s = it.next(); (JAVA的迭代器的起始是从-1位置开始,所以取值是直接取下一个的值,既拆解成为原子操作的话,是先+1再取值)std::string s = *it; it++; (cpp的迭代器的起始是从0位置开始,所以先解引用,再+1)
其他两者一样

数组:

JAVACPP
int[][] arr = new int[n][m];int arr[n][m]; / int **arr = new int[n][m];
arr[a][b];arr[a][b]; / arr[a*m + b] (cpp的数组内存是连续分配的,所以不允许相同层次有不同大小,但这样也允许了通过单层数组的指针来指向多维数组的值)

枚举:此处使用的枚举是c++11后的强类型枚举,更加规范

JAVACPP
enum Color {RED, GREEN}enum class Color {RED, GREEN}
Color a = Color.RED;Color a = Color::RED;

JAVACPP
Stack<Integer> s = new Stack<>();std::stack<int> s;
Integer peek = s.peek();int& top = s.top(); / int top = s.top(); (注意,获取的正常返回是引用,但是我们可以用一个非引用来接,这样就可以避免对容器中数据的修改。后面同理。)
int size = s.size();(JAVA里各种数据类型的size一般都是int)auto size = s.size(); (注意,一般size的数据类型定义都是宏size_type,所以我们用auto比较稳)
boolean empty = s.isEmpty();bool empty = s.empty();
Integer a = s.pop();int top = s.top(); s.pop(); (cpp的pop是没有返回值的,这是因为cpp里从异常处理的角度出发,防止在从容器中删除再拷贝时,如果中间出了错,会导致值丢失,所以让你在pop之前,要自己先用top或者front读一下值)

队列: 尽量还是用双头链表吧

JAVACPP
Queue<String> q = new LinkedList<>();std::queue<std::string> q;
q.add(“a”);s.push(“a”) (cpp的队列和栈的操作英文都是pop和push,但是读值分别是top和front)
boolean out = q.isEmpty();bool out = q.empty();
String a = q.poll();std::string a = q.front(); q.pop(); (注意,cpp里的pop没有返回值)
String a = q.peek();std::string a = q.front();

动态数组

JAVACPP
ArrayList<String> arr = new ArrayList<>();std::vector<std::string> vec;
arr.add(“a”);vec.push_back(“a”);
arr.add(1, “b”);vec.insert(vec.begin() + 1, “b”);
boolean out = arr.isEmpty();bool out = arr.empty();
String a = arr.get(1);std::string a = vec.at(1); / std::string a = vec[1];
arr.addAll(new ArrayList<>());vec.insert(vec.end(), b.begin(), b.end());
arr.remove(“a”); / arr.remove(1);vec.erase(vec.begin() + 1); (不能根据元素的内容进行删除。)
arr.sort((String a2, String b2) -> { return b2.compareTo(a2); }); / arr.sort((a2, b2) -> { return b2.compareTo(a2); }); / arr.sort(Comparator.reverseOrder()); / Collections.sort(arr, Comparator.reverseOrder());bool myFun(int a, int b) {return a < b;}; std::sort(vec.begin(); vec.end(); myFun); (cpp中可以只排序一个容器中的部分元素,所以是传入迭代器)
arr.set(0, “aa”);vec[0] = “aa”; / vec.at(0) = “aa”; (因为at返回的是引用,也可以作为左值,但是要注意,要是没有add就直接设值,不会生效。)

双头链表

JAVACPP
LinkedList<String> l = new LinkedList<String>();std::deque<std::string> d;
l.addFirst(“a”);d.push_front(“a”);
l.addLast(“a”);d.push_back(“a”);
String s = l.getFirst();std::string s = d.front();
String s = l.getLast();std::string s =d.back();
String s = l.removeFirst();std::string s = d.front(); d.pop_front(“a”);
String s = l.removeLast();std::string s =d.back(); d.pop_back(“a”);

Set

JAVACPP
HashSet<String> s = new HashSet<>();std::set<std::string> s;
s.add(“a”);s.insert(“a”)
boolean out = s.isEmpty();bool out = s.empty();
s.remove(“a”);s.erase(s.find(“a”)) (cpp的erase只能处理迭代器)
s.contains(“a”);bool out = (s.count(“a”) == 1)

Map(CPP中的hashmap是unordered_map,正常的map是有序的使用红黑树实现的)

JAVACPP
HashMap<String, String> m = new HashMap<>();std::map<std::string, std::string> m;
m.put(“a”, “b”);m.insert(std::pair<std::string, std::string>(“a”, “b”)); / m[“a”] = “b”; (注意:1、不可以用m.insert(“a”, “b”);2、用insert插入时,如果key已经被占用了,则不会覆盖原值,但是用[]会覆盖原值;3、虽然cpp的map是有序的,但是m[3]这种下标取值,[]中间的只能是key值类型,而不会是插入的顺序,插入顺序只能通过迭代器(map.begin() + n)这种相对方式来获取)
m.get(“a”);std::string& s = m[“a”]; / std::string s = m[“a”] (对于下标取值,可以是引用也可以拷贝,所有的容器都是这样,后面就不再复述了。)
m.remove(“a”);m.erase(m.find(“a”));
boolean out = m.containsKey(“a”);bool out = (m.count(“a”) == 1)
Set<String> k = m.keySet();
Collections<String> v = m.values();
Set<Map.Entry<String, String>> e = m.entrySet();只能通过增强for循环,直接获取到std::pair<std::string, std::string>

优先队列

JAVACPP
PriorityQueue<String> p = new PriorityQueue<>(); / PriorityQueue<String> p = new PriorityQueue<>(Comparator.reverseOrder()); (JAVA的堆默认是最小堆,cpp默认是最大堆)std::priority_queue<std::string> p;
p.add(“a”)p.push(“a”)
String s = p.peek();std::string s = p.top();
String s = p.poll();std::string s = p.top(); p.pop();

总结:

JAVA:判空之所以都是用isEmpty(),是因为这个是Collections容器的方法,同理还有:size、contains、add、remove;map因为不是继承collection接口,所以不用add而是用put来增加元素;栈、队列、优先队列是因为本身有各自特有的命名方式,所以没有用collection的通用名称。

CPP:cpp的容器类之间没有继承上的关系,主要还是靠设计语言的统一。

接口设计

接口设计时,没有一个固定结构的接口设计规范,但是,一定要考虑你的接口能返回所有的结果可能。

最常用的,你的接口要保证你能够返回正常情况值和异常情况值。

比如如果你当前层是做数据透传的,从底层获取一个byte数组,然后返回这个byte数组给上层,如果你跟上层定的接口就是直接返回这个byte的话,就会有问题,因为你处理不了你从底层获取不到数据时,怎么给上层返回。所以一个合理的设计,是你返回一个结构体,结构体有两个字段,一个状态码,另一个是你透传的byte数组。

再比如你是生产数据的,然后你返回给上层的本来就是一个结构体,这个时候我们看到很多设计上是没有返回状态码的。那是因为你当报错时,你可能直接就给上层抛出一个Exception来表达异常,或者直接返回一个null,如果没有这些设计的话,也得在结构体里设计一个状态码。

再举一个C语言的例子,mkdir函数,在正常的返回值外,还会通过修改errno这个全局变量来表述错误值。

综上,就是接口一定要能够表达所有的返回情况,一般最简单的,就是在返回值里加一个状态码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值