如何优化这种多个if条件相同,结果不同的代码

类似于这种

private CompanyFill check_fill(HttpServletRequest request) {
        String s = new String();
        CompanyFill cfill = new CompanyFill();
        cfill.setFillTime(request.getParameter("fillTime"));

        s = request.getParameter("id");
        if (s != null && Tools.isInteger(s))
            cfill.setId(Integer.parseInt(s));
        s = request.getParameter("enterpriceId");
        if (s != null && Tools.isInteger(s))
            cfill.setEnterpriceId(Integer.parseInt(s));
        s = request.getParameter("fillyear");
        if (s != null && Tools.isInteger(s))
            cfill.setFillyear(Integer.parseInt(s));
        s = request.getParameter("status");
        if (s != null && Tools.isInteger(s))
            cfill.setStatus(Integer.parseInt(s));

        s = request.getParameter("gdp");
        if (s != null && Tools.isNumeric(s))
            cfill.setGdp(Double.parseDouble(s));
        s = request.getParameter("daysOfWork");
        if (s != null && Tools.isNumeric(s))
            cfill.setDaysOfWork(Double.parseDouble(s));
        s = request.getParameter("hoursOfDay");
        if (s != null && Tools.isNumeric(s))
            cfill.setHoursOfDay(Double.parseDouble(s));
        s = request.getParameter("totalHour");
        if (s != null && Tools.isNumeric(s))
            cfill.setTotalHour(Double.parseDouble(s));
        s = request.getParameter("totalElec");
        if (s != null && Tools.isNumeric(s))
            cfill.setTotalElec(Double.parseDouble(s));
        return cfill;
    }

3个回答

传递字符串进行分支选择

加一个这个方法,依次调用

/**
     * 
     * @param a 判断参数
     * @param b 标记 1 判断integer 2 判断数字
     * @return
     */
    public boolean isPass(String a,int b){
        switch (b) {
        case 1:
             if (a != null && Tools.isInteger(a))
                 return true;
        case 2:
             if (a != null && Tools.isNumeric(a))
                 return true;
        default:
            break;
        }
        return false;
    }

把s!=null提到外面

改switchcase见仁见智 我觉得没卵用

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
大量的if,如何优化代码
bean里大量的相同的字段,每个字段都有isChecked和content属性,所以需要每一个都判断一遍是否选中,选中再显示内容 稍微举下例子 ``` public class FittingsInfo { private Field companyCn;//中文公司名 private Field companyEn;//英文公司名 private Field tel;//电话 private Field orderNum;//订单号 ... ... } public class Field { private boolean isChecked; private String content; ... ... ``` setter getter constructor都省略了 然后 ``` if (fittingsInfo.getCompanyCn().isChecked()) { ... } if (fittingsInfo.getCompanEn().isChecked()) { ... } ``` 里面逻辑全一样,少说得有三十多个字段,就一个判断几百行出去了....有没有什么办法简化代码呢
下面代码,如果有多个最大相同子串该怎么全部打印出来??
/* * 获取两个字符串中最大相同子串。 * 思路: * 1,先判断两个字符串谁的长度大 * 2,判断较小的字符串是否为较长字符串的子串,如果是就返回较短的字符串 * 3,将较小字符串,按照 正向 和 反向 和 两边同时递减 3种方式依次递减掉1个字符,分别与较长字符串比较, 返回相同字符串长度最长的字符串并打印,如果出现相同长度的匹配字符子串,就以最大长度为参照,将符合 度的字符串全部打印。 */ public class StringTest4 { public static void main(String[] args) { // TODO Auto-generated method stub String s1 = "abcchellonvnbbbbbb...k"; String s2 = "hfkdsajlsahello,jkljlkbbbbb"; String s3 = "aaa"; String s4 = "bbb"; sop(getMaxString(s1, s2)); sop(getMaxString(s3, s4)); } public static void sop(String s) { System.out.println(s); } public static String getMaxString(String s1, String s2) { String max; String min; max = (s1.length() > s2.length()) ? s1 : s2; min = (max == s1) ? s2 : s1; sop("较长字符串为:"+max + "较短字符串为:" + min); for (int x = 0; x < min.length(); x++) { for (int y = 0, z = min.length() - x; z != min.length() + 1; y++, z++) { String temp = min.substring(y, z); if (max.contains(temp)) { return temp; } } } return "无匹配字符"; } } -------------------打印结果--------------------------- 较长字符串为:hfkdsajlsahello,jkljlkbbbbb较短字符串为:abcchellonvnbbbbbb...k hello 较长字符串为:bbb较短字符串为:aaa 无匹配字符 -------------ps------------------ 在s1和s2中有两个字符串符合最大相同的子串,但是比较后得到第一个子串"hello"方法就会结束了,怎么做到一起打印输出? 如果提供的数据有更多的最大相同子串呢?应该怎么修改程序才能把所有匹配条件的子串都输出?
这是一个MD5加密工具类,登陆始终是失败的,我用相同的密码123456多次注册发现加密后的密码字符串都是不同的,是不是工具类有错误的原因?
``` package com.easy.demo.utils; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Arrays; /*这是一个非常好用的使用MD5+salt加密的工具类。使用这个工具类,非常简单, 从前台拿到密码password,直接HexUtil.getEncryptedPwd(password)就可以返回一个长度为56的字符串, 可以用来保存到数据库中,相反,登录的时候,因为MD5加密是不可逆的运算,只能拿用户输入的密码走一遍MD5+salt加密之后, 跟数据库中的password比较,看是否一致,一致时密码相同,登录成功,通过调用HexUtil.validpassword(String password,String dbpassword)方法, 就可以了,不用再做其他事。*/ public class MD5Util { private final static String HEX_NUMS_STR = "0123456789ABCDEF"; private final static Integer SALT_LENGTH = 12; /** * 将16进制字符串转换成数组 * * @return byte[] * @author jacob * */ public static byte[] hexStringToByte(String hex) { /* len为什么是hex.length() / 2 ? * 首先,hex是一个字符串,里面的内容是像16进制那样的char数组 * 用2个16进制数字可以表示1个byte,所以要求得这些char[]可以转化成什么样的byte[],首先可以确定的就是长度为这个char[]的一半 */ int len = (hex.length() / 2); byte[] result = new byte[len]; char[] hexChars = hex.toCharArray(); for (int i = 0; i < len; i++) { int pos = i * 2; result[i] = (byte) (HEX_NUMS_STR.indexOf(hexChars[pos]) << 4 | HEX_NUMS_STR .indexOf(hexChars[pos + 1])); } return result; } /** * 将数组转换成16进制字符串 * * @return String * @author jacob * * */ public static String byteToHexString(byte[] salt){ StringBuffer hexString = new StringBuffer(); for (int i = 0; i < salt.length; i++) { String hex = Integer.toHexString(salt[i] & 0xFF); if(hex.length() == 1){ hex = '0' + hex; } hexString.append(hex.toUpperCase()); } return hexString.toString(); } /** * 密码验证 * @param password 用户输入密码 * @param dbpassword 数据库保存的密码 * @return * @throws NoSuchAlgorithmException * @throws UnsupportedEncodingException */ public static boolean validpassword(String password, String dbpassword) throws NoSuchAlgorithmException, UnsupportedEncodingException{ byte[] pwIndb = hexStringToByte(dbpassword); //定义salt byte[] salt = new byte[SALT_LENGTH]; System.arraycopy(pwIndb, 0, salt, 0, SALT_LENGTH); //创建消息摘要对象 MessageDigest md = MessageDigest.getInstance("MD5"); //将盐数据传入消息摘要对象 md.update(salt); md.update(password.getBytes("UTF-8")); byte[] digest = md.digest(); //声明一个对象接收数据库中的口令消息摘要 byte[] digestIndb = new byte[pwIndb.length - SALT_LENGTH]; //获得数据库中口令的摘要 System.arraycopy(pwIndb, SALT_LENGTH, digestIndb, 0,digestIndb.length); //比较根据输入口令生成的消息摘要和数据库中的口令摘要是否相同 if(Arrays.equals(digest, digestIndb)){ //口令匹配相同 return true; }else{ return false; } } /** * 获得md5之后的16进制字符 * @param password 用户输入密码字符 * @return String md5加密后密码字符 * @throws NoSuchAlgorithmException * @throws UnsupportedEncodingException */ public static String getEncryptedPwd(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException{ //拿到一个随机数组,作为盐 byte[] pwd = null; SecureRandom sc= new SecureRandom(); byte[] salt = new byte[SALT_LENGTH]; sc.nextBytes(salt); //声明摘要对象,并生成 MessageDigest md = MessageDigest.getInstance("MD5"); //计算MD5函数 md.update(salt); //password.getBytes("UTF-8")将输入密码变成byte数组,即将某个数装换成一个16进制数 md.update(password.getBytes("UTF-8")); //计算后获得字节数组,这就是那128位了即16个元素 byte[] digest = md.digest(); pwd = new byte[salt.length + digest.length]; System.arraycopy(salt, 0, pwd, 0, SALT_LENGTH); System.arraycopy(digest, 0, pwd, SALT_LENGTH, digest.length); return byteToHexString(pwd); } } //controller层实现登陆的代码 @RequestMapping(value={"/login"}, method=RequestMethod.GET) public boolean login(HttpServletRequest request, @Param(value = "number")String number, @Param(value = "password")String password) throws UnsupportedEncodingException, NoSuchAlgorithmException { password = HexUtil.getEncryptedPwd(password); User user = userMapper.loginUser(number,password); if(user != null){ return true; }else{ return false; } } ``` 密码输入多遍始终登陆失败,尝试注册相同密码发现,每次注册123456加密后的密码都不一样,是不是MD5工具类有错误?
PDO执行的SQL代码与已有内容相同就返回0
用ajax发送post数据给php页面处理,php页面上用pdo对数据库更新。 php页面中使用如下语句判断exec是否执行成功。 if($pdo->exec($sql))return 1; else return 0; 很奇怪,只要提交的数据没有变化(即相同SQL代码),就会返回0,随便修改数据再提交就可以返回1。 我把sql代码拿出来在phpMyAdmin里多次直接执行,每次都会成功并提示“影响1行”,这说明mysql里没变总是会执行吧。 上网查资料后知道exec返回的是影响的行数,我不知道是不是因为这个。 请问:PDO下相同代码执行第二遍,exec是否就会返回0?如何判断exec返回0是因为数据库不需要更新,而不是出错呢?
PTA上的题目 请问这两段代码有什么区别吗
对任意一个自然数N ​0 ​​ ,先将其各位数字相加求和,再将其和乘以3后加上1,变成一个新自然数N ​1 ​​ ;然后对N ​1 ​​ 重复这种操作,可以产生新自然数N ​2 ​​ ;……多次重复这种操作,运算结果最终会得到一个固定不变的数N ​k ​​ ,就像掉入一个数字“陷阱”。 本题要求对输入的自然数,给出其掉入“陷阱”的过程。 输入格式: 在一行内给出一个自然数N ​0 ​​ (N ​0 ​​ <30000)。 输出格式: 对于输入的N ​0 ​​ ,逐行输出其掉入陷阱的步骤。第i行描述N掉入陷阱的第i步,格式为: i:N ​i ​​ (i≥1)。当某一步得到的自然数结果N ​k ​​ (k≥1)与上一步N ​k−1 ​​ 相同时,停止输出。 这一段有一个测试点通不过: int main() { int x,cnt = 0,sum0,sum1; scanf("%d", &x); while (1) { sum1 = 0; while (x>0) { sum1 += x % 10; x /= 10; } sum1 = sum1*3+1; cnt++; printf("%d:%d\n", cnt, sum1); if (sum0==sum1) { goto out; } x = sum1; sum0 = sum1; } out: return 0; } 这一段完全正确: int cmd(int n) { int m=0,temp; while(n>0) { m=m+n%10; n=n/10; } temp=3*m+1; return temp; } int main() { int n,t,count=1; scanf("%d",&n); while(1) { t=cmd(n); printf("%d:%d\n",count,t); count++; if(n==t) break; n=t; } return 0; } --------------------- 版权声明:本文为CSDN博主「南路上的西城」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_41611106/article/details/82454159 这两个难道有什么不一样吗?
修改MYSQL数据库函数里插入新数据更改插入条件
片段代码如下: IF substring(tmptext1,z,1)<>CHAR(13) AND POSITION('"' IN substring(tmptext1,z,1))<1 AND POSITION('"' IN substring(tmptext1,j,1))<1 AND POSITION(',' IN substring(tmptext1,z,1))<1 AND POSITION(',' IN substring(tmptext1,j,1))<1 AND POSITION(')' IN substring(tmptext1,z,1))<1 AND POSITION(')' IN substring(tmptext1,j,1))<1 THEN SET @createsql = CONCAT("INSERT ignore INTO " , targettable , "(firstname,secondname,id)VALUES('",substring(tmptext1,j,1),"','",substring(tmptext1,z,1),"','",tid,"')"); PREPARE stmt from @createsql; EXECUTE stmt; 现在的是默认插入一行数据,我想修改为firstname,secondname(两个字段集合唯一索引)字段相同的话,id追加到现在的id字段,两个ID之间加个逗号分隔。 ![图片说明](https://img-ask.csdn.net/upload/201910/14/1571044803_840407.png) 目前插入结果是这样的三列,可以看得出firstname和secondname字段多个都是重复的,如“动故”,“动神”,“动明”是重复出现,我想要达到的效果是: ![图片说明](https://img-ask.csdn.net/upload/201910/14/1571044871_640587.png) 也就是“动故”出现一次了,不需要再插入一条数据,只需要更改ID字段就可以,ID字段我设置了最长字符限制,也就是插入10次后就插入不进去数据了,插入语句里添加了ignore,插入不进去也不会报错是不是这样,谢谢。 ![图片说明](https://img-ask.csdn.net/upload/201910/14/1571044933_458071.png) 字段我已经设置为唯一索引,需要还需要补充什么资料,我再添加,谢谢。 问题解决方法参考内容(有内容我也没看明白,大致就是这个意思) https://www.cnblogs.com/kzfbk/p/7780950.html
求这个题代码的算法设计和流程图
问题描述 YOYO非常喜欢CICI,今天他终于向CICI表白了,但是CICI当然不会随随便便的接受,她想找个聪明的男朋友。于是她给YOYO出了个难题,她要求YOYO从商店里中找出一块巧克力。这听 起来不算什么,但是这块巧克力的要求可真是让YOYO犯难了,要求如下: 1、这块巧克力一定要是商店里质量最大的; 2、这块巧克力一定要是质量最大的巧克力中最薄的; 3、这块巧克力一定要是符合前两条的巧克力中编码最大的(每块巧克力都有一个互不相同的编码,越大表示生产日期越近)。 相关的资料到是有,可是,手工从几百块巧克力中选出符合要求的那块…… 不过YOYO说,这个问题写个小的程序就能解决了。聪明的你一定知道他是怎么解决的吧。 输入: 有多组数据,第一行一个数字T,表示测试数据的组数。之后有T组数据。 每组数据的第一行为一个整数 N( N<1000000),表示商店里所有巧克力的数量。 之后N行,每行三个整数,分别表示一块巧克力的质量L、厚度D和编码M(一个9位整数),所有数字保证最高位非零。 输出: 共有T行,第i行只有一个9位整数,表示第i组数据中选出的那块巧克力的编码。 样例输入: 1 4 3000 50 872198442 3000 45 752498124 2000 60 765128742 3000 45 652278122 样例输出: 752498124 #include int main() { int n; scanf("%d",&n); while(n--) { int m,a,b,c; int a1,b1,c1; scanf("%d",&m); scanf("%d %d %d",&a,&b,&c); for(int i = 1;i < m;i++ ) { scanf("%d %d %d",&a1,&b1,&c1); if(a < a1 || (a == a1 && b > b1) || (a == a1 && b == b1 && c < c1)) { a = a1,b = b1,c = c1; } } printf("%d\n",c); } return 0; }
大家线上Java应用的热更新都是怎么实现的?
热更新的时候需要注意哪些点呢? 下面是从网上找到的两种解决方法: 解决方案一 : 自定义类加载器。 首先需要明白一点,class相等的判断条件不仅仅是类名相同,还需要加载它的ClassLoader相同。JVM内部规定一个ClassLoader不可以重复定义类,也就是说想要重定义一个类,就必须使用一个全新的ClassLoader。 JVM内部class被卸载的条件及其苛刻,甚至没有明确的方法可以直接调用,只有当加载该类型的类加载器实例为unreachable状态时,也就是没有任何实例,class才有可能被卸载。(启动类加载器实例永远为reachable状态,由启动类加载器加载的类型可能永远不会被卸载) ``` public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { Class<?> clazz = null; // 首先检查请求的类型是否已经被这个类装载器装载到命名空间中了,如果已经装载,直接返回;否则继续。 if (name.startsWith("com.wafer") || name.contains("Service")) { if (resolve) { resolveClass(clazz); // 链接指定的 Java 类 } // 如果class类被修改过,则重新加载 MoeLoader hcl = new MoeLoader(url); clazz = customLoad(name, hcl); return (clazz); } // 如果类的包名为"java."开始,则有系统默认加载器加载 try { // 得到系统默认的加载cl ClassLoader system = ClassLoader.getSystemClassLoader(); clazz = system.loadClass(name); // 加载名称为 name的类 if (clazz != null) { if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore } return customLoad(name, this); } ``` 此范例的核心在于缓存自己已经加载的class,当再次需要加载时,如果发生变更,则可以new一个ClassLoader,这样新的字节码便可以即时生效。 JRbel是一种热更新的方案,它实现的方式是通过在启动参数中添加javaagent,即JVM底层提供的Instrumentation技术,来改变生成对象的方式。 解决方法二: java.lang.instrument这个类很早就出了,redefineClasses这个方法可以更新方法级别的代码,但是不会触发一个类的初始化方法。游戏服务器的bug基本上只需要方法级别的更新就可以了,因为很多重大的bug基本在测试阶段被修复了,少量偶线的bug出现之后有些时候仅仅只需要改动一行代码却有时不得不需要重启所有应用程序,代价都似乎有点大。 现在开始从instrument入手 ``` public static void premain(String agentArgs, Instrumentation inst); public static void agentmain(String agentArgs, Instrumentation inst); ``` 这两个方法都可以获取到Instrumentation对象,通过redefineClasses方法就可以更新对应的方法了 如果是调用premain这个方法 则需要在程序启动的时候指定对应的jar 同时项目里必须引用这个jar 因为获取到这个引用 java -javaagent:agent.jar -jar xx.jar 例如这样 执行这条命令后程序会查找 agent.jar 里的MANIFEST.MF文件里的Premain-Class参数 设置对应的代理类路径就行。例如:Premain-Class: com.test.JavaAgent 还需要加上 Can-Redefine-Classes: true这个参数才能调用redefineClasses方法。同时 可以拦截对应的类添加标记 做性能分析 agentmain 是通过指定对应的进程pid来加载对应的agent.jar 很典型的jconsule jvisualvm都是通过选择java进程来做一个简单的内存 和cpu分析 ,线程dump .Agent-Class 和上面一样 ``` package com.test; import java.lang.instrument.Instrumentation; public class JavaAgent { public static Instrumentation INST = null; public static void premain(String agentArgs, Instrumentation inst){ INST = inst; } } ``` 这里保存下引用就可以了 ,单独打成agent.jar ``` package com.test; import java.io.FileInputStream; import java.lang.instrument.ClassDefinition; public class Test { public static void main(String[] args) { getInfo(); testhot(); } public final static void testhot(){ new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub while(true){ try { if(JavaAgent.INST != null){ FileInputStream is = new FileInputStream("/Users/xxxx/Downloads/Student.class"); byte[] array = new byte[is.available()]; is.read(array); is.close(); Class cls = Class.forName("com.test.Student"); JavaAgent.INST.redefineClasses(new ClassDefinition(cls,array)); } Thread.sleep(1000); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }).start(); } public final static void getInfo(){ new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub while(true){ //System.out.println("=============="+JavaAgent.INST); new Student().getName(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }).start(); } } ``` 上面就是一个很简单的例子,一个线程在不停的循环检测更新这个类,另外的一个线程在不停的输出这个对象对应的方法输出信息。 测试之后可以发现 ,方法的输出信息已经改变了。
怎么修改下面的代码,关于两数求和
``` #include<iostream> #include<string> #include<math.h> using namespace std; struct LinkNode { int data; //记录每个节点的整数(小于10000) LinkNode *next; //记录下一个节点的地址 LinkNode *prev; //记录前一个节点的地址 }; class LinkList { private: LinkNode *head0,*head1; //head0,head1分别记录两个整数链表的头指针 LinkNode *currptr; LinkNode *result; //result记录结果链表的头指针 public: LinkList(); //构造函数,初始化链表 ~LinkList(); //析构函数,释放空间 void Creat(string a); //引入字符串,创立两个链表,分别表示两个整数 void Add(); //实现两个整数相加 void Display(); //显示结果 void addtwo(); //节点多的作为被加数,少的作为加数,实现整数绝对值大的加小的 }; int sum(int n); LinkList::LinkList() //构造函数,初始化链表 { head0=new LinkNode; //申请一个空间记录整数的符号和节点数 head1=new LinkNode; head0->next=head0; head0->prev=head0; //初始化链表,建立双向循环链表 head1->next=head1; head1->prev=head1; result=new LinkNode; result->next=result; result->prev=result; currptr=NULL; } LinkList::~LinkList() //析构函数,释放空间 { LinkNode *p1=head0,*p2=head1,*p3=result; //三个指针分别指向三条链表的头指针 while(p1!=p1->prev) { p1->prev->next=p1->next; p1->next->prev=p1->prev; currptr=p1; p1=p1->next; delete currptr; } while(p2!=p2->prev) //逐个删除节点,释放空间 { p2->prev->next=p2->next; p2->next->prev=p2->prev; currptr=p2; p2=p2->next; delete currptr; } while(p3!=p3->prev) { p3->prev->next=p3->next; p3->next->prev=p3->prev; currptr=p3; p3=p3->next; delete currptr; } // 删除 p1,p2,p3; } void LinkList::Creat(string a) //引入字符串,创立两个链表,分别表示两个整数 { int i=0,j=0,m=0,n=0,k=0,l=0,s=0,w=0; //i记录字符串,j记录加数节点数;s记录被加数节点数,w标记字符串中的'-'号, //k记录字符串中的字符转化为整数的值,l使每个节点记录4位 while(a[m]!=';') m++; //m记录字符串中被加数的字符数 n=m; while(a[n]!='\0') n++; //n记录字符串的总字符数 if(a[0]=='-') { head0->data=(-1); //记录整数符号 w=1; } else {head0->data=1;} for(i=m-1;i>=w;i--) { if(a[i]!=',') //把字符转化为整数 { k+=(a[i]-'0')*sum(l); l++; } if(a[i]==','||i==w) { currptr=new LinkNode; //把整数存到双向循环链表中 currptr->data=k; currptr->next=head0; currptr->prev=head0->prev; head0->prev->next=currptr; head0->prev=currptr; head0=currptr; s++; //节点数加1 k=0; //重新初始化k和l l=0; } } head0->prev->data*=s; //存储整数符号和节点数 //与建第一个整数链表一样,建立第二个整数链表head1 k=0;l=0; if(a[m+1]=='-') { head1->data=(-1); m++; } else head1->data=1; for(i=n-1;i>m;i--) { if(a[i]!=',') { k+=(a[i]-'0')*sum(l); l++; } if(a[i]==','||i==m+1) { currptr=new LinkNode; currptr->data=k; currptr->next=head1; currptr->prev=head1->prev; head1->prev->next=currptr; head1->prev=currptr; head1=currptr; j++; k=0; l=0; } } head1->prev->data*=j; } void LinkList::Add() //实现两个整数相加 { LinkNode *temp; if(abs(head0->prev->data)>abs(head1->prev->data)) //两个整数中,绝对值大的为被加数 addtwo(); else if(abs(head0->prev->data)<abs(head1->prev->data)) { temp=head0; head0=head1; head1=temp; addtwo(); } else if(abs(head0->prev->data)==abs(head1->prev->data)) { int k1,k2; LinkNode *p=head0,*q=head1; //如果节点数相同,则判断节点中数值大小 while(p->data==q->data&&p!=head0->prev->prev&&q!=head1->prev->prev) { p=p->next; q=q->next; } k1=p->data; k2=q->data; if(k1>k2) addtwo(); else { temp=head0; head0=head1; head1=temp; addtwo(); } } } void LinkList::addtwo() //节点多的作为被加数,少的作为加数,实现整数绝对值大的加小的 //默认head0存的整数绝对值比head1大 { int s=0,m1=head0->data,m2=head1->data; m1=(head0->prev->data/abs(head0->prev->data)); //head0的符号 m2=(head1->prev->data/abs(head1->prev->data)); //head1的符号 LinkNode *p=head0->prev->prev,*q=head1->prev->prev; result->data=head0->prev->data; //存结果的节点数和符号 while(q!=head1->prev) //head0存的整数绝对值比head1大,即head0的节点数大于或等于head1 { currptr=new LinkNode; currptr->data=(p->data)*m1+(q->data)*m2+s; //两整数相加 if((m1*m2)>0) //如果符号相同 { if(abs(currptr->data)-10000>=0) //相加后超过10000,则进位 { s=currptr->data/10000; currptr->data=abs(currptr->data)%10000; } else //abs(currptr->data)-10000<0,不进位 { s=0; currptr->data=abs(currptr->data); } } else if(m1>0&&m2<0) //符号不同,在此相当于实现两个正整数相减 { s=0; if(currptr->data<0) //小于0,向前一位借1 { currptr->data+=10000; s=-1; } } else if(m1<0&&m2>0) //符号不同,在此相当于实现负整数加上正整数 { s=0; if(currptr->data>0) //大于0, { currptr->data=10000-currptr->data; s=1; } else currptr->data=abs(currptr->data); } currptr->next=result; //存入链表 currptr->prev=result->prev; result->prev->next=currptr; result->prev=currptr; result=currptr; p=p->prev; q=q->prev; } //当head0节点数比head1长时,继续建立链表 while(p!=head0->prev) { currptr=new LinkNode; currptr->data=p->data*m1+s; s=currptr->data/10000; if((m1*m2)>0) { if(abs(currptr->data)-10000>=0) { s=currptr->data/10000; currptr->data=abs(currptr->data)%10000; } else {s=0;currptr->data=abs(currptr->data);} } else if(m1>0&&m2<0) { s=0; if(currptr->data<0) { currptr->data+=10000; s=-1; } } else if(m1<0&&m2>0) { s=0; if(currptr->data>0) { currptr->data=10000-currptr->data; s=1; } else currptr->data=abs(currptr->data); } currptr->data=abs(currptr->data)%10000; currptr->next=result; currptr->prev=result->prev; result->prev->next=currptr; result->prev=currptr; result=currptr; p=p->prev; } if(s!=0) //处理相加后,进位问题 { currptr=new LinkNode; currptr->data=abs(s); currptr->next=result; currptr->prev=result->prev; result->prev->next=currptr; result->prev=currptr; result=currptr; result->prev->data=m1*(abs(result->prev->data)+1); } } void LinkList::Display() //显示结果 { LinkNode *p=result; int FuHao=result->prev->data/abs(result->prev->data);//结果的符号 while(p->data==0&&p!=result->prev->prev) //当运算后前几个节点的数据为0时,不输出 { p=p->next; result->prev->data=(abs(result->prev->data)-1)*FuHao; //结果记录非0节点数 } cout<<FuHao*p->data; //首先显示符号和第一个节点中的数 if(abs(result->prev->data)!=1) p=p->next; //判断非0节点数是否为1 while(p!=result->prev->prev) //继续输出 { cout<<","; //每4位一组,并用','隔开 cout.width(4); cout.fill('0'); cout<<p->data; p=p->next; } if(p==result->prev->prev&&abs(result->prev->data)!=1) //显示最后一个节点数据 { cout<<","; cout.width(4); cout.fill('0'); cout<<p->data; } cout<<endl; } int sum(int n) //计算10的乘方 { int i,s=1; for(i=1;i<=n;i++) { s=s*10; } return s; } int main() //主函数 { cout<<"* 任意长整数的加法 *\n\n"; cout<<"* 注意:输入时每四位用逗号隔开 *\n\n"; cout<<"* 如:123456789 *\n\n"; cout<<"* 输入格式为:1,2345,6789 *\n\n"; cout<<"* 两个数之间用';'隔开 *\n\n"; cout<<"\n"; string ch; cout<<"请输入整数1;整数2:\n"; cin>>ch; //输入任意长字符串 LinkList List; //定义链表对象 List.Creat(ch); //把字符串转化为整数,并存到链表中 List.Add(); //实现两个整数相加 cout<<"两整数的和为:"; List.Display(); //输出结果 } ``` 这个代码里输入两个数的时候要用“;”隔开,这个地方怎么改成让它分别输入两个数然后相加,我改成下面这种但前面格式好像不对,不知道怎么改 string ch1,ch2; cout<<"请输入整数1:\n"; cin>>ch1; cout<<"请输入整数2:\n"; cin>>ch2; LinkList List; List.Creat(ch1,ch2); List.Add(); cout<<"两整数的和为:"; List.Display(); }
小白求答,写了个猜字母的代码,可是它识别不了我的答案,求大神解惑
import java.util.Scanner; public class Guess { public static void main(String[] args) { // TODO Auto-generated method stub //第一步:定义数据结构: /*Input:*/ char[] chs = new char[5];//保存随机生成的5个字母 char[] input = new char[5];//保存用户输入的5个字母 /*Output:*/ //第几次尝试,猜对几个字母,几个字母的位置正确 int times=0,right=0,position=0; int score=0;//分数 char[] realtime=new char[5];//保存实时显示猜对位置字母的数组 /*隐含变量*/ String inStr=" ";//临时保存从控制台录入的字符串 /*process*/ generate(chs); /*打桩测试*/ for(int i=0;i<chs.length;i++){ System.out.print(chs[i]+","); } /*主程序循环*/ Scanner sc=new Scanner(System.in);//只有从控制台获得用户输入就用Scanner System.out.println("游戏开始..."); //循环 /*字符串不是基本类型,做等值比较,不能用== * 应该使用Java专门的API比较字符串是否相等 * 语法:字符串1.equals(字符串2); */ while(!inStr.equals("EXIT")&&position!=chs.length){ System.out.println("请输入5个字母,按回车继续...(exit-退出)"); //Step2:获得用户输入: /*获得用户输入的字符串:sc.next()——返回输入整个字符串 * 防止、去掉空格:字符串.trim()——去掉字符前后空格 * 将输入的字符串中所有的小写字母,统一转换为大写字母: * 字符串.toUpperCase() */ inStr=sc.next().trim().toUpperCase(); //Stpe3:判断:如果用户输入的不是exit,才继续 if(!inStr.equals("EXIT")){ //Stpe4:将字符串,转化为字符数组,保存到input数组中 //将字符串转换为字符数组的API:字符数组=字符串.toCharArray() input=inStr.toCharArray(); //Step5:比较chs和input两个数组的相似程度 //得到right:猜对几个字母 //得到position:猜对位置的有几个 //得到realtime:猜对位置的实时数组 int[] result=compare(chs,input,realtime); right=result[0]; position=result[1]; //Step6:如果没有都猜对 if(position!=chs.length){ //将尝试次数+1 times++; System.out.println("第"+times+"次尝试:"+"猜对了" +right+"个字母,"+"其中"+position+ "个位置正确"); for(int i=0;i<realtime.length;i++){ System.out.print(realtime[i]+","); } System.out.println(); } } } /*如果推出循环,只有两种情况: * 1用户输入exit,主动退出,输入欢迎下次再来 * 2用户猜对了(position==chs.length) * 计算得分:100*chs.length-10*times * 输出,恭喜你猜对了 * */ if(inStr.equals("EXIT")){ System.out.println("欢迎下次再来!"); }else{ score=100*chs.length-10*times; System.out.println("恭喜您,猜对了,本次得分:"+score); } } /** * 比较两个数组 * 1.求出猜对几个字母,有几个字母的位置正确 * 2.将比较结果分别保存在返回值数组的第一个元素和第二个元素中 * 3.将位置正确的字母在realtime中实时显示 * @param chs 随机生成的目标数组 * @param input 用户输入的数组 * @param realtime 实时显示猜对位置的元素数组 * @return 1个数:[0]保存猜对字母的个数 * [1]保存猜对位置的个数 */ public static int[] compare(char[]chs,char[]input,char[]realtime){ //数组的第一个元素[0],表示有几个相同的字母 //数组第二个元素[1],表示位置有几个相同的字母 int[] result=new int[2];//新建两个整数元素的数组 /* * 反复取出input数组中每个元素和chs数组中每个元素比较 * 只有input中的元素和chs中的元素相等 * 对result[0]+1,表示猜对了一个字母 * 立刻判断此时的位置是否相同(i==j) * 如果i==j * 对result[1]+1,表示猜对了一个位置 * 将才对的字母,填入realtime数组相同的位置 */ for(int i=0;i<input.length;i++){ for(int j=0;i<chs.length;i++){ if(input[1]==chs[j]){ result[0]++; if(i==j){ result[1]++; realtime[i]=input[i]; } break; } } } return result; } /** * 自动生成5个不重复的字母,直接保存在数组chs中 * @param chs:传入一个空数组。 * 方法内,对数组的更改,直接作用于原数组 */ public static void generate(char[] chs){ /* * 反复生成多个字母,就要用循环: * 循环变量:int i=0; * 循环条件:i<chs.length; * 迭代循环变量:无规律 * 只有生成字母不重复时,才+1! * 循环体:随机生成65~90之间的1个整数。 * 判断刚生成的整数,在数组中是否重复 * 如果没有重复,就加入数组chs中,并且i++ * (否则什么都不做,再生成一个新字母,再比较) */ //因为循环次数和迭代规律不确定,所以使用while循环 int i = 0;//定义循环变量 while(i<chs.length){ //随机生成65-90之间的整数 int r=(int)(Math.random()*(90-65+1)+65); //判断r是否在数组中包含 //定义1个布尔类型变量,表示r是否可用。默认是ture. boolean enable=true; //循环遍历数组的每个元素,和r比。 //只要任意1个元素等于r,则改变变量enable=false,表示r不可用。 for(int j=0;j<i;j++){ if(chs[j]==r){ enable=false; } } if(enable){//如果r可用 chs[i]=(char)r; i++; } } } } ``` ```
CRC校验代码看不懂,请求高手支招。目前我看不懂的一篇CRC校验文章和一套逆序CRC校验。
#各位大神,我看不懂这篇文章还有一段逆序CRC代码。请各位大神帮帮忙: ## 1、文章(链接地址:https://wenku.baidu.com/view/9f7b55876f1aff00bed51ec0.html) 下面为不完全版 CRC(Cyclic Redundancy Check)校验应用较为广泛,以前为了处理简单,在程序中大多数采用LRC(Longitudinal Redundancy Check)校验,LRC校验很好理解,编程实现简单。用了一天时间研究了CRC的C语言实现,理解和掌握了基本原理和C语言编程。结合自己的理解简单写下来。 1、CRC简介 CRC检验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个检验码r位(就是CRC码),附在信息后面,构成一个新的二进制码序列数共(k+r)位,最后发送出去。接收端根据同样的规则校验,以确定传送中是否出错。接收端有两种处理方式:1、计算k位序列的CRC码,与接收到的CRC比较,一致则接收正确。2、计算整个k+r位的CRC码,若为0,则接收正确。 CRC码有多种检验位数,8位、16位、32位等,原理相同。16位的CRC码产生的规则是先将要发送的二进制序列数左移16位(即乘以2的16次方后),除以一个多项式,最后所得到的余数就是CRC码。 求CRC码所采用的是模2运算法则,即多项式除法中采用不带借位的减法运算,运算等同于异或运算。这一点要仔细理解,是编程的基础。 CRC-16: (美国二进制同步系统中采用) G(X) = X16 + X15 + X2 + 1 CRC-CCITT: (由欧洲CCITT推荐) G(X) = X16 + X12 + X5 + 1 CRC-32: G(X) = X32 + X26 + X23 + X22 + X16 +X12 + X11 + X10 + X8 + X7 + X5 + X4 + X2 + X1 + 1 2、按位计算CRC 采用CRC-CCITT多项式,多项式为0x11021,C语言编程时,参与计算为0x1021,这个地方得深入思考才能体会其中的奥妙,分享一下我的思路:当按位计算CRC时,例如计算二进制序列为1001 1010 1010 1111时,将二进制序列数左移16位,即为1001 1010 1010 1111 (0000 0000 0000 0000),实际上该二进制序列可拆分为1000 0000 0000 0000 (0000 0000 0000 0000) + 000 0000 0000 0000 (0000 0000 0000 0000) + 00 0000 0000 0000 (0000 0000 0000 0000) + 1 0000 0000 0000 (0000 0000 0000 0000) + …… 现在开始分析运算: <1>对第一个二进制分序列求余数,竖式除法即为0x10000 ^ 0x11021运算,后面的0位保留; <2>接着对第二个二进制分序列求余数,将第一步运算的余数*2后再和第二个二进制分序列一起对0x11021求余,这一步理解应该没什么问题。如果该分序列为0,无需计算。 <3>对其余的二进制序列求余与上面两步相同。 <4>计算到最后一位时即为整个二进制序列的余数,即为CRC校验码。 该计算方法相当于对每一位计算,运算过程很容易理解,所占内存少,缺点是一位一位计算比较耗时。 下面给出C语言实现方法: 复制代码 代码如下: ## 第一段代码 unsigned char test[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}; unsigned char len = 16; void main( void ) { unsigned long temp = 0; unsigned int crc; unsigned char i; unsigned char *ptr = test; while( len-- ) { for(i = 0x80; i != 0; i = i >> 1) { temp = temp * 2; if((temp & 0x10000) != 0) temp = temp ^ 0x11021; if((*ptr & i) != 0) temp = temp ^ (0x10000 ^ 0x11021); } ptr++; } crc = temp; printf("0x%x ",crc); } 上面的程序根据运算分析而来,很容易理解。为了节约内存空间,我们对程序作进一步的简化。分析可知,当二进制序列中上一位计算的余数第15bit位为1时,即( 上一位计算的余数 & 0x8000) != 0,计算本位时,上一位余数 * 2后可对0x11021作求余运算,然后再加上本位计算所得余数。这个很好理解,也就是说,打个比方,把它看作简单的除法,计算上一位时的余数乘以2后,如果比较大可以当被除数,就再去除除数求余。有一点和普通除法不同的是,因为多项式除法中采用不带借位的减法运算,所以0x10000也可以被0x11021除,余数并非为0x10000,而是0x1021。这个自己动手算一下就知道了。余数之和也是不带进位的加法运算,即异或。最后还强调一点,因为二进制序列是左移16位后参与运算的,所以,一直算到序列的最后一位也是可以被除的,这点大家要明白。下面给出简化后的C语言实现。 复制代码 代码如下: ## 第二段代码 unsigned char test[16] ={0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}; unsigned char len = 16; void main( void ) { unsigned int crc = 0; unsigned char i; unsigned char *ptr = test; while( len-- ) { for(i = 0x80; i != 0; i = i >> 1) { if((crc & 0x8000) != 0) { crc = crc << 1; crc = crc ^ 0x1021; } else { crc = crc << 1; } if((*ptr & i) != 0) { crc = crc ^ 0x1021; } } ptr++; } printf("0x%x ",crc); } 上面这段程序网上较为常见,但冇得详细的解释。通过我上面的详细分析,如果对此段程序理解还有困难,可以对比一下没简化之前的程序,细细品味一哈,还是比较容易理解的。要是还理解不了,还是从头再看下,我码这么多字容易吗。。。。。 按位计算CRC代码比较简单,所占内存少,但要一位一位去计算,下面再介绍一种按字节查表快速计算CRC的方法。 3、按字节计算CRC 有了上面按位计算的知识,理解这个就是小case了。还是举前面的例子:当字节计算CRC时,例如计算二进制序列为1001 1010 1010 1111时,即0x9a9f时,将二进制序列数左移16位,即为0x9a9f(0 0 0 0),实际上该二进制序列可拆分为0x9a00(0 0 0 0) + 0x009f(0 0 0 0),分析计算时和上面的步骤一样,唯一不同的是计算中上一步的余数CRC要乘以2的八次方参与下一步的运算,这个应该好理解撒。为了简化编程,将计算中的CRC拆成高八位和低八位的形式,高八位的值直接与本位值相加求余,低八位的值乘以2的八次方后作为余数和计算得的余数相加。为了提高计算速度,我们把8位二进制序列数的CRC全部计算出来,放在一个表中,采用查表法可大大提高计算速度。 表是怎么得到的呢?当然是计算出来的,下面的程序给出了多项式是0x11021的计算程序。 复制代码 代码如下: ## 第三段代码 void main( void ) { unsigned int crc = 0; unsigned char i; unsigned int j; for(j = 0; j < 256; j++) { crc = 0; for(i = 0x80; i != 0; i = i >> 1) { if((crc & 0x8000) != 0) { crc = crc << 1; crc = crc ^ 0x1021; } else { crc = crc << 1; } if((j & i) != 0) { crc = crc ^ 0x1021; } } printf("0x"); if(crc < 0x10) { printf("000"); } else if(crc < 0x100) { printf("00"); } else if(crc < 0x1000) { printf("0"); } printf("%x, ",crc); } } 如果你不是使用的0x11021多项式,只需把程序中0x1021换成其他的就可以了。后面的几个printf语句为了控制使生成的表比较整齐,如果无所谓,可直接用printf("0x%x, ",crc);代替。生成的表如下: 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, 好了,我们来写按字节计算的源程序: ## 第六段代码(CRC逆序校验代码) uint8 xCal_crc(uint8 *ptr,uint32 len) { uint8 crc; uint8 i; uint32 lenBak = len; uint8 *ptrBak = ptr; uint32 Debuglen = lenBak; uint8 *Debugptr = ptrBak; char CrcSendBuf[100] = {0}; crc = 0; while(len--) { crc ^= *ptr++; memset(CrcSendBuf, 0, 100); sprintf(CrcSendBuf, "head->crc = %02x \r\n", crc); UartSendString(CrcSendBuf, strlen(CrcSendBuf)); for(i = 0;i < 8;i++) { if(crc & 0x01) { crc = (crc >> 1) ^ 0x8C; } else { crc >>= 1; } } } return crc; }
使用 ListVIew 在指定的 items上如何实现一个 listener 事件?
我创建了一个ListView,包含很多items,但是实际上我不确定在一个特定的items上如何实现一个listener事件? 我使用的下面的代码,但是当我点击任何items,一直显示的是相同的Activity。 list.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1, int position,long id) { Intent i = new Intent(MainActivity.this, Activity2.class); startActivity(i); } }); 但是如果我在下面的代码中使用if语句,也没有用。 list.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1, int position,long id) { if(list.getItemAtPosition(position).equals(mStrings[0])) { Intent i = new Intent(MainActivity.this, Activity2.class); startActivity(i); } } });
带有泛型的接口方法实现类使用反射获取方法参数类型时多一个Object参数
由于业务需要在接口方法中使用了泛型,多个实现类的相同方法传入的实参类型不同,想用反射查看具体的实参类型,进而转换为实参的类型。 但使用中遇到了一个问题,接口定义的方法只有一个“T”参数,反射method.getParameterTypes()却得到两个参数类型,请问各位大牛java内部的实现方式是怎样的? 另外,使用jdk1.8时还会出现反射后的两个参数顺序颠倒的情况,还请各位帮忙分析一下,具体代码如下: 接口 ``` public interface ProcessTestService<T> { void test(T param) throws Exception; } ``` 实现类 ``` public class ProcessTestServiceImpl implements ProcessTestService<Integer> { @Override public void test(Integer param) throws Exception { } } ``` 测试类 ``` public class TestDamo { public static void main(String[] args) { ProcessTestService processTestService = new ProcessTestServiceImpl(); Method[] methodArray = processTestService.getClass().getDeclaredMethods(); labe:for (Method method : methodArray) { if ("test".equals(method.getName())) { for (Class clazz : method.getParameterTypes()){ System.out.println(clazz); } } } } } ```
【急求!】降低算法时间复杂度的方法?附图附代码!多谢!!
**第一次来CSDN求教大神们!恳请多多指教!!我在用matlab编写一个小算法,这个算法里面可能多次循环的嵌套,导致得到最终结果(输入Reader=800,Tag=1000,r=30,范围为[1,900]的时候),花费了将近800多秒!!!劳驾各方神圣给我指点迷津,降低我这个算法的时间复杂度,有什么好点子好方法么?** ------------------------------------- _更新:_原题是RFID网络冗余阅读器去除算法,即要去除掉系统网络中冗余的阅读器,就是图中的红色圈圈,下图是已经去除后的效果。 ------------------------------------- 【算法执行结果图如下】 ![图片说明](https://img-ask.csdn.net/upload/201504/19/1429420208_542810.png) ------------------------------------- * 算法设计: * ① definition: cc(covered count) ——每个tag被reader覆盖的数量(黑点到红圈圆心的距离:D<=r) nc(neighbor count)——每个reader邻居的数量(两个圆圈原点距离:L<=2r) ncc(neighbor cover count)——每个reader的邻居所覆盖的所有tag数量的总和 * ② steps: a.找出所有cc=1的tag,由于这些tag只被独有的reader覆盖,所以这些对应的reader为非冗余reader,其下所覆盖的所有tag均被该reader锁定(hold); b.当所有cc=1对应的reader被找到后,即剩下的tag的cc均>1,剩下的reader根据nc值由低到高依次循环执行c,d,e操作(邻居越多的阅读器在实际中越容易对其他阅读器产生干扰); c.当有多个nc值相等的reader,判断相同nc值的reader的ncc值大小,根据ncc的值由高到低循环进行d,e操作; d.该reader中所有的tag的cc值减1,该reader为冗余reader; e.找出c操作中cc=1的tag,重复a操作,假如依旧没有cc=1的tag,重复b操作; f.直到所有tag均被reader锁定后,去除结束。 ------------------------------------- **【附代码:matlab】** **代码写的不漂亮望大神们见谅!!** **我没有币实在不好意思啊 T_T..** ``` %x1,y1,x2,y2是随机数,在其他函数里产生的已知变量,Reader, Tag, r均为GUI上输入的变量,输出为冗余阅读器数量和整个算法执行的时间 function [tcbaredundant,TCBAtime]=TCBA(x1,y1,x2,y2,Reader,Tag,r) %TCBA算法: tic; %%%%%%%%%%%%%【计算tagcc的值】%%%%%%%%%%%%%%%% tagcc=zeros(1,Tag); for j=1:Reader for i=1:Tag if showdistance(x1(j),y1(j),x2(i),y2(i))<=r tagcc(i)=tagcc(i)+1; end end end % disp(strcat('tagcc: ',num2str(tagcc))); %%%%%%%%%%%%%%%%%%%%%【找出cc=1的tag对应的reader(判断reader是否冗余),对于非冗余的reader所覆盖的tag进行锁定】%%%%%%%%%%%%%%%%%%%%%% tagholder=zeros(1,Tag); readerclosed=zeros(1,Reader); readerredundant=ones(1,Reader); for j=1:Reader for i=1:Tag if showdistance(x1(j),y1(j),x2(i),y2(i))<=r && tagcc(i)==1 && tagholder(i)==0 tagholder(i)=j; for k=1:Tag if showdistance(x1(j),y1(j),x2(k),y2(k))<=r && tagholder(k)==0 tagholder(k)=j; end end readerclosed(j)=1; readerredundant(j)=0; end end end % disp(strcat('tagholder: ',num2str(tagholder))); % disp(strcat('readerclosed: ',num2str(readerclosed))); % disp(strcat('readerredundant: ',num2str(readerredundant))); %%%%%%%%%%%%%【NC】%%%%%%%%%%%%%%%% for a=1:Reader reader.nc(a)=0; reader.ncc(a)=0; for b=1:Reader if showdistance(x1(a),y1(a),x1(b),y1(b))<=2*r && showdistance(x1(a),y1(a),x1(b),y1(b))>0 &&readerclosed(a)==0 && readerredundant(a)==1 reader.nc(a)=reader.nc(a)+1; %%%%%%%%%%%%%【NCC】%%%%%%%%%%%%%%%% for i=1:Tag if showdistance(x1(b),y1(b),x2(i),y2(i))<=r reader.ncc(a)=reader.ncc(a)+1; end end end end end % disp(strcat('reader.nc: ',num2str(reader.nc))); % disp(strcat('reader.ncc: ',num2str(reader.ncc))); %%%%%%%%%%%%%【对于冗余的reader进行操作】%%%%%%%%%%%%%%%% %%%%%%%%%%%%%【根据reader的nc和ncc值由高到低进行筛选】%%%%%%%%%%%%%%%% while (length(find(reader.nc==0))~=Reader) reader.ncmax=find(reader.nc==max(reader.nc)); reader.ncc2=reader.ncc(reader.ncmax); reader.nccmax=reader.ncmax(find(reader.ncc2==max(reader.ncc2))); ncc=reader.nccmax(1); % disp(strcat('reader.ncmax对应rid: ',num2str(reader.ncmax))); % disp(strcat('reader.ncmax对应ncc值(reader.ncc2): ',num2str(reader.ncc2))); % disp(strcat('reader.nccmax对应rid(ncc),即要去除的reader为: ',num2str(ncc))); for k=1:Tag if showdistance(x1(ncc),y1(ncc),x2(k),y2(k))<=r tagcc(k)=tagcc(k)-1; end end reader.nc(ncc)=0; readerclosed(ncc)=1; %对剩下的reader重复最开始的操作进行判断是否为冗余reader for j=1:Reader if readerclosed(j)==0 && readerredundant(j)==1 for i=1:Tag if showdistance(x1(j),y1(j),x2(i),y2(i))<=r && tagcc(i)==1 && tagholder(i)==0 tagholder(i)=j; for h=1:Tag if showdistance(x1(j),y1(j),x2(h),y2(h))<=r && tagholder(h)==0 tagholder(h)=j; end end readerclosed(j)=1; readerredundant(j)=0; end end end end end % disp(strcat('~tagcc: ',num2str(tagcc))); % disp(strcat('~readerclosed: ',num2str(readerclosed))); % disp(strcat('~readerredundant: ',num2str(readerredundant))); % disp(strcat('~reader.nc: ',num2str(reader.nc))); % disp(strcat('~reader.ncc: ',num2str(reader.ncc))); % disp(strcat('~tagholder: ',num2str(tagholder))); %%%%%%%%%%%%%%%%%%%%%【去除没有hold任何标签的reader】%%%%%%%%%%%%%%%%%%%%%% a=unique(tagholder); holderid=a(find(a~=0)); disp(strcat('覆盖有标签的reader的rid为:',num2str(holderid))); cla(gca); for k=holderid sita=0:pi/20:2*pi;%角度[0,2*pi] xr=x1(k)+r*cos(sita); yr=y1(k)+r*sin(sita); readers=plot(xr,yr,'-r'); hold on; end %对坐标轴进行相关设置 [tags,TO,tid]=tag(x2,y2,Tag); h=legend([readers,tags],'reader','tag'); set(h,'color',[1 1 0]); %%%%%%%%%%%%%【计算冗余的reader数量】%%%%%%%%%%%%%%%% tcbaredundant=Reader-length(holderid); fprintf('TCBA算法得到冗余阅读器个数:%d\n',tcbaredundant); %%%%%%%%%%%%%%%%%%%%%【TCBA算法执行所需时间】%%%%%%%%%%%%%%%%%%%%%% time=toc; TCBAtime=num2str(time); fprintf('TCBA算法执行所需时间为:%s秒\n',TCBAtime); fprintf('------------------------------------------------\n'); ```
.Java 中多个 class 的使用问题
**背景:**这是一个教科书上的计算器代码,因为代码中只有第一个是public class,所以我放到同一个.java文件中。 **过程:**用sublime将代码抄到电脑里,在Eclipse中打开却发现是 class 调用错误。检查了一边发现代码和书中相同,找不到错误的地方,随后我为各个class建了各自的.java文档,想这次如果有错误就是书中代码错了,但……显示正常,运行ok。 坑爹,我把代码粘贴回原来的.java文档,复制文档+换文件夹,拷贝的文件没有显示错误。但是class的名字是黄色未被调用(这不是废话么?不能调用你还运行个什么)。我再点击修复,得到 private static final long serialVersionUID = 1L; **秉着打破砂锅问到底的精神,所以**为什么第一次写上代码时是显示错误,复制粘贴之后又 ok 了呢? private static final long serialVersionUID = 1L; 这个量的意义何在? **而且:**只有 DigitButton 调用是 ok 的,剩下的AddButton、SubtractButton、MultiplyButton、ClearButton…ect 全是提示错误。OperatorButton 类被继承也是不可以的。 /** This program implements a simple four-function calculator */ public class come extends Program{ /* Initializes the user interface */ public void init(){ setLayout(new TableLayout(5,4)); display = new CalculatorDisplay(); add(display, "gridwidth=4 height=" + BUTTON_SIZE); addButtons(); addActionListeners(); } public void actionPerformed(ActionEvent e) { Object source = e.getSource(); if(source instanceof CalculatorButton){ ((CalculatorButton) source).action(display); } } private void addButtons(){ String constraint = "width=" + BUTTON_SIZE + " height=" + BUTTON_SIZE; add(new DigitButton(7), constraint); add(new DigitButton(8), constraint); add(new DigitButton(9), constraint); add(new AddButton(), constraint); add(new DigitButton(4), constraint); add(new DigitButton(5), constraint); add(new DigitButton(6), constraint); add(new SubtractButton(), constraint); add(new DigitButton(1), constraint); add(new DigitButton(2), constraint); add(new DigitButton(3), constraint); add(new MultiplyButton(), constraint); add(new ClearButton(), constraint); add(new DigitButton(0), constraint); add(new EqualsButton(), constraint); add(new DivideButton(), constraint); } private static final int BUTTON_SIZE = 40; private CalculatorDisplay display; } class CalculatorDisplay extends IntField{ /* Creates a new calculator display that is not directly editable by the user */ public CalculatorDisplay(){ setEditable(false); setFont(new Font("SansSerif", Font.PLAIN, 24)); setValue(0); startNewValue = false; op = null; } /* Adds a digit to the display, clearing the old value if startNewValue is set */ public void addDigit(int digit){ int value = (startNewValue) ? 0 : getValue(); setValue(10 * value + digit); startNewValue = false; } /* Sets a new operator, applying the previous one if one exists */ public void setOperator(OperatorButton button){ if (op == null){ memory = getValue(); } else { memory = op.apply(memory, getValue()); setValue(memory); } op = button; startNewValue = true; } /* private instance variables */ private OperatorButton op; /* The last operator button pressed */ private int memory; /* The value to which the operator is applied */ private boolean startNewValue; /* Set after an operator to start a new value */ } /* This abstract class is the superclass for every calculator button. Every button must define an action method, which is called whenever the button is cliked. */ abstract class CalculatorButton extends JButton { /* Creates a new CalculatorButton with the specified name */ public CalculatorButton(String name) { super(name); setFont(new Font("SansSerif", Font.PLAIN, 24)); } /* Called when the button is clicked (every subclass must implement this method) */ public abstract void action(CalculatorDisplay display); } /* This class is used for each of the digit buttons. The action consists of adding the digit used as a label on the button, which is returned by getText. */ class DigitButton extends CalculatorButton { /* Creates a new DigitButton for the digit n */ public DigitButton(int n) { super("" + n); } /* Adds this digit to the display */ public void action(CalculatorDisplay display) { display.addDigit(Integer.parseInt(getText())); } } /* This abstract class is the superclass of the various operator buttons. Each concrete subclass must override the apply method. */ abstract class OperatorButton extends CalculatorButton{ /* Creates a new OperatorButton with the specified name */ public OperatorButton(String name) { super(name); } /* Informs the display that this operator button has been clicked */ public void action(CalculatorDisplay display) { display.setOperator(this); } /* Applies this operator (every subclass must implement this method) */ public abstract int apply(int lhs, int rhs); } /* The classes AddButton, SubtractButton, MultipButton, and DicideButton are the same except for their label and the implementation of apply. */ class AddButton extends OperatorButton { public AddButton() { super("+"); } public int apply(int lhs, int rhs) { return lhs + rhs; } } class SubtractButton extends OperatorButton { public SubtractButton() { super("-"); } public int apply(int lhs, int rhs) { return lhs - rhs; } } class MultiplyButton extends OperatorButton { public MultiplyButton() { super("x"); } public int apply(int lhs, int rhs) { return lhs * rhs; } } class DivideButton extends OperatorButton { public DivideButton() { super("/"); } public int apply(int lhs, int rhs) { return lhs / rhs; } } /* The EqualsButton class displays the current value. As it happens, this Operation can be implemented simply by setting the operator to null. */ class EqualsButton extends CalculatorButton { public EqualsButton() { super("C"); } public void action(CalculatorDisplay display) { display.setOperator(null); display.setValue(0); } } public class ClearButton extends CalculatorButton { public ClearButton(){ super("C"); } public void action(CalculatorDisplay display) { display.setOperator(null); display.setValue(0); } }
用python计算括号匹配序列最长公共子序列的问题?
网易的笔试题,代码已经写好,但一直无法100%通过测试,找不到问题所在,想请各位大神不吝赐教。 ``` ''' 一个合法的括号匹配序列被定义为: 1. 空串""是合法的括号序列 2. 如果"X"和"Y"是合法的序列,那么"XY"也是一个合法的括号序列 3. 如果"X"是一个合法的序列,那么"(X)"也是一个合法的括号序列 4. 每个合法的括号序列都可以由上面的规则生成 例如"", "()", "()()()", "(()())", "(((()))"都是合法的。 从一个字符串S中移除零个或者多个字符得到的序列称为S的子序列。 例如"abcde"的子序列有"abe","","abcde"等。 定义LCS(S,T)为字符串S和字符串T最长公共子序列的长度,即一个最长的序列W既是S的子序列也是T的子序列的长度。 小易给出一个合法的括号匹配序列s,小易希望你能找出具有以下特征的括号序列t: 1、t跟s不同,但是长度相同 2、t也是一个合法的括号匹配序列 3、LCS(s, t)是满足上述两个条件的t中最大的 因为这样的t可能存在多个,小易需要你计算出满足条件的t有多少个。 如样例所示: s = "(())()",跟字符串s长度相同的合法括号匹配序列有: "()(())", "((()))", "()()()", "(()())",其中LCS( "(())()", "()(())" )为4,其他三个都为5,所以输出3. 输入描述: 输入包括字符串s(4 ≤ |s| ≤ 50,|s|表示字符串长度),保证s是一个合法的括号匹配序列。 输出描述: 输出一个正整数,满足条件的t的个数。 输入例子1: (())() 输出例子1: 3 ''' ''' 思路:首先利用递归生成与目标序列长度相同的括号匹配序列,然后分别计算目标序列和生成序列的最长公共子序列。 计算方法:先求出目标序列和生成序列长度减1的所有子序列列表,比较两列表是否有公共子序列,若有,则输出子序列的长度,若无,则递归生成 目标序列和生成序列长度减2的所有子序列列表,继续比较,以此类推,直至找到公共子序列 ''' string = input() # 输入括号匹配序列 length = len(string) # 计算序列长度 def generate_string(l): # 利用递归生成与参数长度相同的序列 if l == 2: return ['()'] else: str_l = [i for i in map(lambda x: '()' + x, generate_string(l-2))] str_m = [i for i in map(lambda x: '(' + x + ')', generate_string(l-2))] str_r = [i for i in map(lambda x: x + '()', generate_string(l-2))] str_l.extend(str_m) str_l.extend(str_r) str_l = list(set(str_l)) return str_l g_strings = generate_string(length) # 根据已知的目标长度生成符合条件的序列列表 g_strings.remove(string) # 从生成的序列列表中移除目标序列 def get_children(s): # 得到比参数序列长度小1的子序列 children = [] for i in range(len(s)): children.append(s[:i] + s[i+1:]) children = list(set(children)) return children def lcs(str_as, str_bs): # 计算两个参数序列列表中最长公共子序列的长度 for each_a in str_as: # 若str_as和str_bs间有公共序列,则返回该序列的长度 if each_a in str_bs: return len(each_a) # 若str_as和str_bs间无公共序列 str_as_children = [] str_bs_children = [] for each_a in str_as: # 计算str_as序列列表中所有序列长度减1的子序列列表 str_as_children.extend(get_children(each_a)) for each_b in str_bs: # 计算str_bs序列列表中所有序列长度减1的子序列列表 str_bs_children.extend(get_children(each_b)) str_as_children = list(set(str_as_children)) # 删除重复项 str_bs_children = list(set(str_bs_children)) return lcs(str_as_children, str_bs_children) # 递归计算两个参数序列列表中最长公共子序列的长度 results = [] for each_str in g_strings: # 计算所有生成序列和目标序列的最长公共子序列的长度 results.append(lcs([each_str], [string])) max_lcs = max(results) # 计算需要题目要求输出的结果 count = 0 for each in results: if each == max_lcs: count += 1 print(count) ''' 此程序在测试'((())())'时结果不正确 正确的答案是9 此程序得到的答案是8 ''' ```
flask+mysql实现的web应用,在注册页面点击注册后提示 Instance '<User at 0x5486a10>' has been deleted?
##问题描述 从github(https://github.com/num10/transfile)上下载的一个用flask+mysql实现的转pdf成word的web应用,其中 涉及到新用户的注册: ![图片说明](https://img-ask.csdn.net/upload/201911/07/1573098094_252858.png) 可是在注册页面填完信息点击注册后前端报错如下: ![图片说明](https://img-ask.csdn.net/upload/201911/07/1573098203_905955.png) ``` sqlalchemy.orm.exc.ObjectDeletedError: Instance '<User at 0x58072f0>' has been deleted, or its row is otherwise not present. ``` 根据traceback的信息,定位到出错的位置应该是下图中的models.py和views.py文件 ![图片说明](https://img-ask.csdn.net/upload/201911/07/1573100399_404211.jpg) 后台关于这两个文件的报错信息为: ```ruby File "C:\Users\26808\transfile-master\app\auth\views.py", line 68, in register token = user.generate_confirmation_token() File "C:\Users\26808\transfile-master\app\models.py", line 142, in generate_confirmation_token return s.dumps({'confirm': self.id}).decode('utf-8') ``` 对应文件中: views.py: ```ruby @auth.route('/register', methods=['GET', 'POST']) def register(): form = RegistrationForm() if form.validate_on_submit(): user = User(email=form.email.data, username=form.username.data, password=form.password.data) db.session.add(user) db.session.commit() token = user.generate_confirmation_token() send_email(user.email, '认证您的账户', 'auth/email/confirm', user=user, token=token) flash('认证信息已发送至您的邮箱') return redirect(url_for('auth.login')) return render_template('auth/register.html', form=form) ``` models.py: ``` def generate_confirmation_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'confirm': self.id}).decode('utf-8') ``` ##补充 1.按照requirements文件的要求,flask都安装了正确的包 2.正如register函数中所写的那样,点击注册后用户信息会被加入mysql数据库中但是会被重复加入,即多次运行每次都出错,并且相同的用户被反复加入mysql数据库中 3.网上大多数都是通过app.run()来启动文件的,但是这个项目里面先要设置 ```set FLASK_APP = manage.py``` 在```flask run```才能运行 能解释一下为什么吗? manage.py代码如下: ```ruby #!/usr/bin/ python # -*- coding: UTF-8 -*- import os COV = None if os.environ.get('FLASK_COVERAGE'): import coverage COV = coverage.coverage(branch=True, include='app/*') COV.start() import sys import click from flask_migrate import Migrate,upgrade from app import create_app, db from app.models import User, Follow, Role, Permission, Post, Comment from flask_uploads import configure_uploads from app.auth.forms import pdfs,photos,words app = create_app(os.getenv('FLASK_CONFIG') or 'default') migrate = Migrate(app, db) configure_uploads(app, pdfs) configure_uploads(app, photos) configure_uploads(app, words) @app.shell_context_processor def make_shell_context(): return dict(db=db, User=User, Follow=Follow, Role=Role, Permission=Permission, Post=Post, Comment=Comment) @app.cli.command() @click.option('--coverage/--no-coverage', default=False, help='Run tests under code coverage.') def test(coverage=False): """Run the unit tests.""" if coverage and not os.environ.get('FLASK_COVERAGE'): import subprocess os.environ['FLASK_COVERAGE'] = '1' sys.exit(subprocess.call(sys.argv)) import unittest tests = unittest.TestLoader().discover('tests') unittest.TextTestRunner(verbosity=2).run(tests) if COV: COV.stop() COV.save() print('Coverage Summary:') COV.report() basedir = os.path.abspath(os.path.dirname(__file__)) covdir = os.path.join(basedir, 'tmp/coverage') COV.html_report(directory=covdir) print('HTML version: file://%s/index.html' % covdir) COV.erase() @app.cli.command() @click.option('--length', default=25, help='Number of functions to include in the profiler report.') @click.option('--profile-dir', default=None, help='Directory where profiler data files are saved.') def profile(length=25, profile_dir=None): """Start the application under the code profiler.""" from werkzeug.contrib.profiler import ProfilerMiddleware app.wsgi_app = ProfilerMiddleware(app.wsgi_app, restrictions=[length], profile_dir=profile_dir) app.run(debug=False) @app.cli.command() def deploy(): """Run deployment tasks.""" # migrate database to latest revision upgrade() # create or update user roles Role.insert_roles() # ensure all users are following themselves User.add_self_follows() if __name__ == '__main__': deploy() ``` 数据模型models.py: ``` #!/usr/bin/ python # -*- coding: UTF-8 -*- from datetime import datetime import hashlib from werkzeug.security import generate_password_hash, check_password_hash from itsdangerous import TimedJSONWebSignatureSerializer as Serializer from markdown import markdown import bleach from flask import current_app, request,url_for from flask_login import UserMixin, AnonymousUserMixin from . import db, login_manager class Permission: FOLLOW = 1 COMMENT = 2 WRITE = 4 MODERATE = 8 ADMIN = 16 class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) default = db.Column(db.Boolean, default=False, index=True) permissions = db.Column(db.Integer) users = db.relationship('User', backref='role', lazy='dynamic') def __init__(self, **kwargs): super(Role, self).__init__(**kwargs) if self.permissions is None: self.permissions = 0 @staticmethod def insert_roles(): roles = { 'User': [Permission.FOLLOW, Permission.COMMENT, Permission.WRITE], 'Moderator': [Permission.FOLLOW, Permission.COMMENT, Permission.WRITE, Permission.MODERATE], 'Administrator': [Permission.FOLLOW, Permission.COMMENT, Permission.WRITE, Permission.MODERATE, Permission.ADMIN], } default_role = 'User' for r in roles: role = Role.query.filter_by(name=r).first() if role is None: role = Role(name=r) role.reset_permissions() for perm in roles[r]: role.add_permission(perm) role.default = (role.name == default_role) db.session.add(role) db.session.commit() def add_permission(self, perm): if not self.has_permission(perm): self.permissions += perm def remove_permission(self, perm): if self.has_permission(perm): self.permissions -= perm def reset_permissions(self): self.permissions = 0 def has_permission(self, perm): return self.permissions & perm == perm def __repr__(self): return '<Role %r>' % self.name class Follow(db.Model): __tablename__ = 'follows' follower_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True) followed_id = db.Column(db.Integer, db.ForeignKey('users.id'), primary_key=True) timestamp = db.Column(db.DateTime, default=datetime.utcnow) class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(64), unique=True, index=True) username = db.Column(db.String(64), unique=True, index=True) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) password_hash = db.Column(db.String(128)) confirmed = db.Column(db.Boolean, default=False) name = db.Column(db.String(64)) location = db.Column(db.String(64)) about_me = db.Column(db.Text()) member_since = db.Column(db.DateTime(), default=datetime.utcnow) last_seen = db.Column(db.DateTime(), default=datetime.utcnow) avatar_hash = db.Column(db.String(32)) posts = db.relationship('Post', backref='author', lazy='dynamic') followed = db.relationship('Follow', foreign_keys=[Follow.follower_id], backref=db.backref('follower', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') followers = db.relationship('Follow', foreign_keys=[Follow.followed_id], backref=db.backref('followed', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') comments = db.relationship('Comment', backref='author', lazy='dynamic') @staticmethod def add_self_follows(): for user in User.query.all(): if not user.is_following(user): user.follow(user) db.session.add(user) db.session.commit() def __init__(self, **kwargs): super(User, self).__init__(**kwargs) if self.role is None: if self.email == current_app.config['FLASKY_ADMIN']: self.role = Role.query.filter_by(name='Administrator').first() if self.role is None: self.role = Role.query.filter_by(default=True).first() if self.email is not None and self.avatar_hash is None: self.avatar_hash = self.gravatar_hash() self.follow(self) @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self, password): self.password_hash = generate_password_hash(password) def verify_password(self, password): return check_password_hash(self.password_hash, password) def generate_confirmation_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'confirm': self.id}).decode('utf-8') def confirm(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token.encode('utf-8')) except: return False if data.get('confirm') != self.id: return False self.confirmed = True db.session.add(self) return True def generate_reset_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'reset': self.id}).decode('utf-8') @staticmethod def reset_password(token, new_password): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token.encode('utf-8')) except: return False user = User.query.get(data.get('reset')) if user is None: return False user.password = new_password db.session.add(user) return True def can(self, perm): return self.role is not None and self.role.has_permission(perm) def is_administrator(self): return self.can(Permission.ADMIN) def ping(self): self.last_seen = datetime.utcnow() db.session.add(self) def gravatar_hash(self): return hashlib.md5(self.email.lower().encode('utf-8')).hexdigest() def gravatar(self, size=100, default='identicon', rating='g'): url = 'https://secure.gravatar.com/avatar' hash = self.avatar_hash or self.gravatar_hash() return '{url}/{hash}?s={size}&d={default}&r={rating}'.format( url=url, hash=hash, size=size, default=default, rating=rating) def follow(self, user): if not self.is_following(user): f = Follow(follower=self, followed=user) db.session.add(f) def unfollow(self, user): f = self.followed.filter_by(followed_id=user.id).first() if f: db.session.delete(f) def is_following(self, user): if user.id is None: return False return self.followed.filter_by( followed_id=user.id).first() is not None def is_followed_by(self, user): if user.id is None: return False return self.followers.filter_by( follower_id=user.id).first() is not None @property def followed_posts(self): return Post.query.join(Follow, Follow.followed_id == Post.author_id)\ .filter(Follow.follower_id == self.id) def to_json(self): json_user = { 'url': url_for('api.get_user', id=self.id), 'username': self.username, 'member_since': self.member_since, 'last_seen': self.last_seen, 'posts_url': url_for('api.get_user_posts', id=self.id), 'followed_posts_url': url_for('api.get_user_followed_posts', id=self.id), 'post_count': self.posts.count() } return json_user def generate_auth_token(self, expiration): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'id': self.id}).decode('utf-8') @staticmethod def verify_auth_token(token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return None return User.query.get(data['id']) def __repr__(self): return '<User %r>' % self.username class AnonymousUser(AnonymousUserMixin): def can(self, permissions): return False def is_administrator(self): return False login_manager.anonymous_user = AnonymousUser @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id)) class Post(db.Model): __tablename__ = 'posts' id = db.Column(db.Integer, primary_key=True) body = db.Column(db.Text) body_html = db.Column(db.Text) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) author_id = db.Column(db.Integer, db.ForeignKey('users.id')) comments = db.relationship('Comment', backref='post', lazy='dynamic') @staticmethod def on_changed_body(target, value, oldvalue, initiator): allowed_tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code', 'em', 'i', 'li', 'ol', 'pre', 'strong', 'ul', 'h1', 'h2', 'h3', 'p'] target.body_html = bleach.linkify(bleach.clean( markdown(value, output_format='html'), tags=allowed_tags, strip=True)) def to_json(self): json_post = { 'url': url_for('api.get_post', id=self.id), 'body': self.body, 'body_html': self.body_html, 'timestamp': self.timestamp, 'author_url': url_for('api.get_user', id=self.author_id), 'comments_url': url_for('api.get_post_comments', id=self.id), 'comment_count': self.comments.count() } return json_post @staticmethod def from_json(json_post): body = json_post.get('body') if body is None or body == '': raise ValidationError('post does not have a body') return Post(body=body) db.event.listen(Post.body, 'set', Post.on_changed_body) class Comment(db.Model): __tablename__ = 'comments' id = db.Column(db.Integer, primary_key=True) body = db.Column(db.Text) body_html = db.Column(db.Text) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) disabled = db.Column(db.Boolean) author_id = db.Column(db.Integer, db.ForeignKey('users.id')) post_id = db.Column(db.Integer, db.ForeignKey('posts.id')) @staticmethod def on_changed_body(target, value, oldvalue, initiator): allowed_tags = ['a', 'abbr', 'acronym', 'b', 'code', 'em', 'i', 'strong'] target.body_html = bleach.linkify(bleach.clean( markdown(value, output_format='html'), tags=allowed_tags, strip=True)) db.event.listen(Comment.body, 'set', Comment.on_changed_body) ```
多个div浮窗的只有一个能移动的问题
同一个页面 显示多个div浮窗(多个浮窗的内容并不一样,也在不同的div中 演示代码里是只举例了一种) 只有一个能移动 请问那个是判断我现在移动的是哪个浮窗 ,怎么才能分别移动 不冲突呢? 如果我描述的不够清楚 我还可以补充说明。 演示代码如下: ``` <html> <head> <title>Js弹出浮动窗口,支持鼠标拖动和关闭</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script type="text/javascript"> /** 关于一些参数说明: *bodycontent:要在窗口显示的内容,dom对象 *title:窗口标题,字符串类型 *removeable:窗口能否拖动,布尔类型 *注意:内容窗体的高度是height-30px,请计算好你要显示的内容的高度和宽度。弹出窗的id为"223238909",所以你的页面不要再取值为"223238909"的id了,以防js执行出错*/ function createdialog(width,height,bodycontent,title,removeable){ if(document.getElementById("www_jb51_net")==null){ /*创建窗口的组成元素*/ var dialog = document.createElement("div"); var dialogtitlebar= document.createElement("div"); var dialogbody = document.createElement("div"); var dialogtitleimg = document.createElement("span"); var dialogtitle = document.createElement("span"); var dialogclose = document.createElement("span"); var closeaction = document.createElement("button"); /*为窗口设置一个id,id如此怪异是为了尽量避免与其他用户取的id相同而出错*/ dialog.id = "223238909"; /*组装对话框标题栏,按从里到外的顺序组装*/ dialogtitle.innerHTML = title; dialogtitlebar.appendChild(dialogtitleimg); dialogtitlebar.appendChild(dialogtitle); dialogtitlebar.appendChild(dialogclose); dialogclose.appendChild(closeaction); /*组装对话框主体内容*/ if(bodycontent!=null){ bodycontent.style.display = "block"; dialogbody.appendChild(bodycontent); } /*组装成完整的对话框*/ dialog.appendChild(dialogtitlebar); dialog.appendChild(dialogbody); /*设置窗口组成元素的样式*/ var templeft,temptop,tempheight//窗口的位置(将窗口放在页面中间的辅助变量) var dialogcssText,dialogbodycssText;//拼出dialog和dialogbody的样式字符串 templeft = (document.body.clientWidth-width)/2; temptop = (document.body.clientHeight-height)/2; tempheight= height-30; dialogcssText= "position:absolute;background:#65c294;padding:1px;border:4px;top:"+temptop+"px;left:"+templeft+"px;height:"+height+"px;width:"+width+"px;"; dialogbodycssText = "width:100%;background:#ffffff;"+"height:" + tempheight + "px;"; dialog.style.cssText = dialogcssText; dialogtitlebar.style.cssText = "height:30px;width:100%;background:url(images/titlebar.png) repeat;cursor:move;"; dialogbody.style.cssText = dialogbodycssText; dialogtitleimg.style.cssText = "float:left;height:20px;width:20px;background:url(images/40.gif);"+"display:block;margin:4px;line-height:20px;"; dialogtitle.style.cssText = "font-size:16px;float:left;display:block;margin:4px;line-height:20px;"; dialogclose.style.cssText = "float:right;display:block;margin:4px;line-height:20px;"; closeaction.style.cssText = "height:20px;width:24px;border-width:1px;"+"background-image:url(images/close.png);cursor:pointer;"; /*为窗口元素注册事件*/ var dialogleft = parseInt(dialog.style.left); var dialogtop = parseInt(dialog.style.top); var ismousedown = false;//标志鼠标是否按下 /*关闭按钮的事件*/ closeaction.onclick = function(){ dialog.parentNode.removeChild(dialog); } /*实现窗口的移动,这段代码很典型,网上很多类似的代码*/ if(removeable == true){ var ismousedown = false; var dialogleft,dialogtop; var downX,downY; dialogleft = parseInt(dialog.style.left); dialogtop = parseInt(dialog.style.top); dialogtitlebar.onmousedown = function(e){ ismousedown = true; downX = e.clientX; downY = e.clientY; } document.onmousemove = function(e){ if(ismousedown){ dialog.style.top = e.clientY - downY + dialogtop + "px"; dialog.style.left = e.clientX - downX + dialogleft + "px"; } } /*松开鼠标时要重新计算当前窗口的位置*/ document.onmouseup = function(){ dialogleft = parseInt(dialog.style.left); dialogtop = parseInt(dialog.style.top); ismousedown = false; } } return dialog; }//end if(if的结束) } </script> <style> table{background:#b2d235;} button{font-size:12px;height:23;background:#ece9d8;border-width:1;} #linkurl,#linkname,#savelink{width:100px;} </style> </head> <body> <!-- 显示窗口的地方 --> <div id="here"></div><a id="clickhere" href="#">点击生成窗口</a> <!-- 要嵌入到窗口的内容 --> <div id="login" style="display:none;"> <form action="#" method="post" onSubmit="return false;"> <table width="400" height="95"> <tr> <td width="78">链接文字</td> <td width="168"><input name="link.name" type="text" value="浮窗测试"/></td> <td width="138" id="linktext"></td> </tr> <tr> <td>链接地址</td> <td><input name="link.url" type="text" value="f"/></td> <td id="linkurl"></td> </tr> <tr> <td></td> <td><button type="submit" style="float:right;">添加</button></td> <td id="savelink"></td> </tr> </table> </form> </div> <script type="text/javascript"> var here = document.getElementById("here"); var login = document.getElementById("login"); var clickhere = document.getElementById("clickhere"); clickhere.onclick = function(){ here.appendChild(createdialog(400,95+30,login,"中国外汇交易中心",true)); } </script> </body> </html> ```
Java学习的正确打开方式
在博主认为,对于入门级学习java的最佳学习方法莫过于视频+博客+书籍+总结,前三者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现学习的最好方式就是阅读参考官方文档其次就是国内的书籍,博客次之,这又是一个层次了,这里暂时不提后面再谈。博主将为各位入门java保驾护航,各位只管冲鸭!!!上天是公平的,只要不辜负时间,时间自然不会辜负你。 何谓学习?博主所理解的学习,它是一个过程,是一个不断累积、不断沉淀、不断总结、善于传达自己的个人见解以及乐于分享的过程。
程序员必须掌握的核心算法有哪些?
由于我之前一直强调数据结构以及算法学习的重要性,所以就有一些读者经常问我,数据结构与算法应该要学习到哪个程度呢?,说实话,这个问题我不知道要怎么回答你,主要取决于你想学习到哪些程度,不过针对这个问题,我稍微总结一下我学过的算法知识点,以及我觉得值得学习的算法。这些算法与数据结构的学习大多数是零散的,并没有一本把他们全部覆盖的书籍。下面是我觉得值得学习的一些算法以及数据结构,当然,我也会整理一些看过...
大学四年自学走来,这些私藏的实用工具/学习网站我贡献出来了
大学四年,看课本是不可能一直看课本的了,对于学习,特别是自学,善于搜索网上的一些资源来辅助,还是非常有必要的,下面我就把这几年私藏的各种资源,网站贡献出来给你们。主要有:电子书搜索、实用工具、在线视频学习网站、非视频学习网站、软件下载、面试/求职必备网站。 注意:文中提到的所有资源,文末我都给你整理好了,你们只管拿去,如果觉得不错,转发、分享就是最大的支持了。 一、电子书搜索 对于大部分程序员...
linux系列之常用运维命令整理笔录
本博客记录工作中需要的linux运维命令,大学时候开始接触linux,会一些基本操作,可是都没有整理起来,加上是做开发,不做运维,有些命令忘记了,所以现在整理成博客,当然vi,文件操作等就不介绍了,慢慢积累一些其它拓展的命令,博客不定时更新 free -m 其中:m表示兆,也可以用g,注意都要小写 Men:表示物理内存统计 total:表示物理内存总数(total=used+free) use...
比特币原理详解
一、什么是比特币 比特币是一种电子货币,是一种基于密码学的货币,在2008年11月1日由中本聪发表比特币白皮书,文中提出了一种去中心化的电子记账系统,我们平时的电子现金是银行来记账,因为银行的背后是国家信用。去中心化电子记账系统是参与者共同记账。比特币可以防止主权危机、信用风险。其好处不多做赘述,这一层面介绍的文章很多,本文主要从更深层的技术原理角度进行介绍。 二、问题引入 假设现有4个人...
程序员接私活怎样防止做完了不给钱?
首先跟大家说明一点,我们做 IT 类的外包开发,是非标品开发,所以很有可能在开发过程中会有这样那样的需求修改,而这种需求修改很容易造成扯皮,进而影响到费用支付,甚至出现做完了项目收不到钱的情况。 那么,怎么保证自己的薪酬安全呢? 我们在开工前,一定要做好一些证据方面的准备(也就是“讨薪”的理论依据),这其中最重要的就是需求文档和验收标准。一定要让需求方提供这两个文档资料作为开发的基础。之后开发...
网页实现一个简单的音乐播放器(大佬别看。(⊙﹏⊙))
今天闲着无事,就想写点东西。然后听了下歌,就打算写个播放器。 于是乎用h5 audio的加上js简单的播放器完工了。 演示地点演示 html代码如下` music 这个年纪 七月的风 音乐 ` 然后就是css`*{ margin: 0; padding: 0; text-decoration: none; list-...
Python十大装B语法
Python 是一种代表简单思想的语言,其语法相对简单,很容易上手。不过,如果就此小视 Python 语法的精妙和深邃,那就大错特错了。本文精心筛选了最能展现 Python 语法之精妙的十个知识点,并附上详细的实例代码。如能在实战中融会贯通、灵活使用,必将使代码更为精炼、高效,同时也会极大提升代码B格,使之看上去更老练,读起来更优雅。
数据库优化 - SQL优化
以实际SQL入手,带你一步一步走上SQL优化之路!
通俗易懂地给女朋友讲:线程池的内部原理
餐盘在灯光的照耀下格外晶莹洁白,女朋友拿起红酒杯轻轻地抿了一小口,对我说:“经常听你说线程池,到底线程池到底是个什么原理?”
经典算法(5)杨辉三角
杨辉三角 是经典算法,这篇博客对它的算法思想进行了讲解,并有完整的代码实现。
使用 Docker 部署 Spring Boot 项目
Docker 技术发展为微服务落地提供了更加便利的环境,使用 Docker 部署 Spring Boot 其实非常简单,这篇文章我们就来简单学习下。首先构建一个简单的 S...
英特尔不为人知的 B 面
从 PC 时代至今,众人只知在 CPU、GPU、XPU、制程、工艺等战场中,英特尔在与同行硬件芯片制造商们的竞争中杀出重围,且在不断的成长进化中,成为全球知名的半导体公司。殊不知,在「刚硬」的背后,英特尔「柔性」的软件早已经做到了全方位的支持与支撑,并持续发挥独特的生态价值,推动产业合作共赢。 而对于这一不知人知的 B 面,很多人将其称之为英特尔隐形的翅膀,虽低调,但是影响力却不容小觑。 那么,在...
面试官:你连RESTful都不知道我怎么敢要你?
干货,2019 RESTful最贱实践
刷了几千道算法题,这些我私藏的刷题网站都在这里了!
遥想当年,机缘巧合入了 ACM 的坑,周边巨擘林立,从此过上了"天天被虐似死狗"的生活… 然而我是谁,我可是死狗中的战斗鸡,智力不够那刷题来凑,开始了夜以继日哼哧哼哧刷题的日子,从此"读题与提交齐飞, AC 与 WA 一色 ",我惊喜的发现被题虐既刺激又有快感,那一刻我泪流满面。这么好的事儿作为一个正直的人绝不能自己独享,经过激烈的颅内斗争,我决定把我私藏的十几个 T 的,阿不,十几个刷题网...
白话阿里巴巴Java开发手册高级篇
不久前,阿里巴巴发布了《阿里巴巴Java开发手册》,总结了阿里巴巴内部实际项目开发过程中开发人员应该遵守的研发流程规范,这些流程规范在一定程度上能够保证最终的项目交付质量,通过在时间中总结模式,并推广给广大开发人员,来避免研发人员在实践中容易犯的错误,确保最终在大规模协作的项目中达成既定目标。 无独有偶,笔者去年在公司里负责升级和制定研发流程、设计模板、设计标准、代码标准等规范,并在实际工作中进行...
SQL-小白最佳入门sql查询一
不要偷偷的查询我的个人资料,即使你再喜欢我,也不要这样,真的不好;
redis分布式锁,面试官请随便问,我都会
文章有点长并且绕,先来个图片缓冲下! 前言 现在的业务场景越来越复杂,使用的架构也就越来越复杂,分布式、高并发已经是业务要求的常态。像腾讯系的不少服务,还有CDN优化、异地多备份等处理。 说到分布式,就必然涉及到分布式锁的概念,如何保证不同机器不同线程的分布式锁同步呢? 实现要点 互斥性,同一时刻,智能有一个客户端持有锁。 防止死锁发生,如果持有锁的客户端崩溃没有主动释放锁,也要保证锁可以正常释...
项目中的if else太多了,该怎么重构?
介绍 最近跟着公司的大佬开发了一款IM系统,类似QQ和微信哈,就是聊天软件。我们有一部分业务逻辑是这样的 if (msgType = "文本") { // dosomething } else if(msgType = "图片") { // doshomething } else if(msgType = "视频") { // doshomething } else { // doshom...
Nginx 原理和架构
Nginx 是一个免费的,开源的,高性能的 HTTP 服务器和反向代理,以及 IMAP / POP3 代理服务器。Nginx 以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。 Nginx 的整体架构 Nginx 里有一个 master 进程和多个 worker 进程。master 进程并不处理网络请求,主要负责调度工作进程:加载配置、启动工作进程及非停升级。worker 进程负责处...
“狗屁不通文章生成器”登顶GitHub热榜,分分钟写出万字形式主义大作
一、垃圾文字生成器介绍 最近在浏览GitHub的时候,发现了这样一个骨骼清奇的雷人项目,而且热度还特别高。 项目中文名:狗屁不通文章生成器 项目英文名:BullshitGenerator 根据作者的介绍,他是偶尔需要一些中文文字用于GUI开发时测试文本渲染,因此开发了这个废话生成器。但由于生成的废话实在是太过富于哲理,所以最近已经被小伙伴们给玩坏了。 他的文风可能是这样的: 你发现,...
程序员:我终于知道post和get的区别
是一个老生常谈的话题,然而随着不断的学习,对于以前的认识有很多误区,所以还是需要不断地总结的,学而时习之,不亦说乎
《程序人生》系列-这个程序员只用了20行代码就拿了冠军
你知道的越多,你不知道的越多 点赞再看,养成习惯GitHub上已经开源https://github.com/JavaFamily,有一线大厂面试点脑图,欢迎Star和完善 前言 这一期不算《吊打面试官》系列的,所有没前言我直接开始。 絮叨 本来应该是没有这期的,看过我上期的小伙伴应该是知道的嘛,双十一比较忙嘛,要值班又要去帮忙拍摄年会的视频素材,还得搞个程序员一天的Vlog,还要写BU...
加快推动区块链技术和产业创新发展,2019可信区块链峰会在京召开
11月8日,由中国信息通信研究院、中国通信标准化协会、中国互联网协会、可信区块链推进计划联合主办,科技行者协办的2019可信区块链峰会将在北京悠唐皇冠假日酒店开幕。   区块链技术被认为是继蒸汽机、电力、互联网之后,下一代颠覆性的核心技术。如果说蒸汽机释放了人类的生产力,电力解决了人类基本的生活需求,互联网彻底改变了信息传递的方式,区块链作为构造信任的技术有重要的价值。   1...
Java世界最常用的工具类库
Apache Commons Apache Commons有很多子项目 Google Guava 参考博客
程序员把地府后台管理系统做出来了,还有3.0版本!12月7号最新消息:已在开发中有github地址
第一幕:缘起 听说阎王爷要做个生死簿后台管理系统,我们派去了一个程序员…… 996程序员做的梦: 第一场:团队招募 为了应对地府管理危机,阎王打算找“人”开发一套地府后台管理系统,于是就在地府总经办群中发了项目需求。 话说还是中国电信的信号好,地府都是满格,哈哈!!! 经常会有外行朋友问:看某网站做的不错,功能也简单,你帮忙做一下? 而这次,面对这样的需求,这个程序员...
网易云6亿用户音乐推荐算法
网易云音乐是音乐爱好者的集聚地,云音乐推荐系统致力于通过 AI 算法的落地,实现用户千人千面的个性化推荐,为用户带来不一样的听歌体验。 本次分享重点介绍 AI 算法在音乐推荐中的应用实践,以及在算法落地过程中遇到的挑战和解决方案。 将从如下两个部分展开: AI算法在音乐推荐中的应用 音乐场景下的 AI 思考 从 2013 年 4 月正式上线至今,网易云音乐平台持续提供着:乐屏社区、UGC...
【技巧总结】位运算装逼指南
位算法的效率有多快我就不说,不信你可以去用 10 亿个数据模拟一下,今天给大家讲一讲位运算的一些经典例子。不过,最重要的不是看懂了这些例子就好,而是要在以后多去运用位运算这些技巧,当然,采用位运算,也是可以装逼的,不信,你往下看。我会从最简单的讲起,一道比一道难度递增,不过居然是讲技巧,那么也不会太难,相信你分分钟看懂。 判断奇偶数 判断一个数是基于还是偶数,相信很多人都做过,一般的做法的代码如下...
为什么要学数据结构?
一、前言 在可视化化程序设计的今天,借助于集成开发环境可以很快地生成程序,程序设计不再是计算机专业人员的专利。很多人认为,只要掌握几种开发工具就可以成为编程高手,其实,这是一种误解。要想成为一个专业的开发人员,至少需要以下三个条件: 1) 能够熟练地选择和设计各种数据结构和算法 2) 至少要能够熟练地掌握一门程序设计语言 3) 熟知所涉及的相关应用领域的知识 其中,后两个条件比较容易实现,而第一个...
Android 9.0 init 启动流程
阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android本篇文章主要介绍Android开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:一、启动流程概述一、 启动流程概述Android启动流程跟Linux启动类似,大致分为如下五个阶段。1.开机上电,加载固化的ROM。2.加载BootLoader,拉起Android OS。3.加载Uboot,初始外设,引导Kernel启动等。...
8年经验面试官详解 Java 面试秘诀
作者 |胡书敏 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 本人目前在一家知名外企担任架构师,而且最近八年来,在多家外企和互联网公司担任Java技术面试官,前后累计面试了有两三百位候选人。在本文里,就将结合本人的面试经验,针对Java初学者、Java初级开发和Java开发,给出若干准备简历和准备面试的建议。 Java程序员准备和投递简历的实...
相关热词 c# clr dll c# 如何orm c# 固定大小的字符数组 c#框架设计 c# 删除数据库 c# 中文文字 图片转 c# 成员属性 接口 c#如何将程序封装 16进制负数转换 c# c#练手项目
立即提问