热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

就我那点垃圾代码竟然也有人要抄?

小弟不才,去年学习flutter的过程中,搞过几个小玩具,其中就有一个将json数据转换成dartclass的idea插件。不想点的朋友可以看一下gif

小弟不才,去年学习 flutter 的过程中,搞过几个小玩具,其中就有一个将 json 数据转换成 dart class 的 idea 插件。

gayhub 传送门

不想点的朋友可以看一下 gif

就我那点垃圾代码竟然也有人要抄?

半年多来,随着 flutter 的火热,github 上也有了那么几十个 star。后来我也发布到了全家桶插件官网。陆陆续续也有几千个的下载量了。对于我这个小透明来说,还是挺开心的,不管写得有多烂,总归是有人在用,总归是为 flutter 的生态贡献了自己的一点绵薄之力。

然而就在今天,当我想去看看那些下载量更高的同类项目的时候,很不凑巧的就让我发现了这么一个作品:

先上一张他的 gif 吧

就我那点垃圾代码竟然也有人要抄?

敏感的我,一下子就感觉到了有点不对劲,于是我点开了他的源码开始查看,有如下收获:

我先看了下源码目录

我的

就我那点垃圾代码竟然也有人要抄?

他的

就我那点垃圾代码竟然也有人要抄?

1.ClassGenerator 类名一样的

2.NameValuePair/NamePair 极其相似,而且讲道理,NamePair 这个命名很不自然

3.Param 类名一样

4.Util/Utils 基本没差别

于是我开始对比代码细节

没耐心的朋友可以不用看代码,我以我的人格担保,最后的结论是没错的

ClassGenerator

我的

class ClassGenerator(private val generateComments: Boolean, private val ignoreEmptyOrNull: Boolean) {
    val classes = mutableMapOf>()

    fun generate(name: String, string: String): String {
        return try {
            val parseResult = JsonParser().parse(string)

            val json: JsonObject? = if (parseResult.isJsonObject) {
                parseResult.asJsonObject
            } else if (parseResult.isJsonArray) {
                parseResult.asJsonArray[0].asJsonObject
            } else null

            val fields = Param.json2Params(json)
            "class $name {\n${printClassWithParams(fields, 2, name)}\n}\n${buildClasses()}"
        } catch (jsonParseException: JsonParseException) {
            jsonParseException.printStackTrace()
            "error: not supported json"
        } catch (illegalStateException: IllegalStateException) {
            illegalStateException.printStackTrace()

            if (illegalStateException.message?.startsWith("Not a JSON Object") == true) {
                "error: not supported json"
            } else {
                "error: unknown"
            }
        }
    }

    private fun printClassWithParams(params: List, space: Int, className: String): String {
        val commentSb = StringBuilder()
        val sb = StringBuilder()

        val tempClasses = HashMap>() // 统计子类

        var spaceStr = ""
        repeat(space) { spaceStr += " " }

        val commentPrefix = "$spaceStr *"
        fun List.insertComment(): List  {
            return if (generateComments) this.map {
                commentSb.append(commentPrefix).append(" ${it.comment}\n")
                it
            } else this
        }

        /* 基本类型参数声明与统计 **/
        val orderedList = params
                .filter { it.key == "String" || it.key == "int" || it.key == "double" || it.key == "bool" || (!ignoreEmptyOrNull && it.key == "dynamic") }
                .sortedBy { it.key }
                .insertComment()
                .map {
                    sb.append("$spaceStr${it.key} ${it.value};\n")
                    it.value
                }

        /* 对象类型参数声明与统计 **/
        val objectList = params
                .filter { it.key == "object" }
                .sortedBy { it.value }
                .insertComment()
                .map {
                    val clazzName = Util.toUpperCaseFirstOne(it.value + "Bean")
                    classes[clazzName] =  it.clazz
                    tempClasses[clazzName] = it.clazz
                    sb.append(spaceStr).append(clazzName).append(" ").append(it.value).append(";").append("\n")
                    NameValuePair(clazzName, it.value)
                }

        /* 基本类型 list 参数声明与统计 **/
        val listBaseList = params
                .filter { it.key.startsWith("List<") }
                .filterNot { it.key.contains("null") }
                .sortedBy { it.value }
                .insertComment()
                .map {
                    sb.append(spaceStr).append(it.key).append(" ").append(it.value).append(";").append("\n")
                    NameValuePair(it.key, it.value)
                }

        /* 对象类型 list 参数声明与统计 **/
        val listList = params
                .filter { "list" == it.key }
                .filter { it.clazz != null }
                .sortedBy { it.value }
                .insertComment()
                .map {
                    val clazzName = Util.toUpperCaseFirstOne(it.value + "ListBean")
                    classes[clazzName] = it.clazz
                    tempClasses[clazzName] = it.clazz
                    sb.append(spaceStr).append("List<").append(clazzName).append(">").append(" ").append(it.value).append(";").append("\n")
                    NameValuePair(clazzName, it.value)
                }

        /* dynamic list **/
        var dynamiclist: List? = null
        if (!ignoreEmptyOrNull) {
            dynamiclist = params
                    .filter { it.key == "dynamicList" }
                    .sortedBy { it.value }
                    .insertComment()
                    .map {
                        sb.append(spaceStr).append("List").append(" ").append(it.value).append(";").append("\n")
                        NameValuePair(it.key, it.value)
                    }
        }

        val tempSpaceStr = "$spaceStr  "

        /* map.value 转换为对象的静态函数 start **/
        val fieldName = Util.toLowerCaseFirstOne(className)
        sb.append("\n").append(spaceStr)
                .append("static ").append(className).append(" fromMap").append("(Map map) {")
                .append("\n").append(tempSpaceStr)
                .append(className).append(" ").append(fieldName).append(" = new ").append(className).append("();")

        orderedList.forEach {
            sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(it).append(" = ").append("map['").append(it).append("'];")
        }

        dynamiclist?.forEach {
            sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(it.value).append(" = ").append("map['").append(it.value).append("'];");
        }

        objectList.forEach {
            sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(it.value).append(" = ").append(it.name).append(".fromMap(map['").append(it.value).append("']);")
        }

        listList.forEach {
            sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(it.value).append(" = ").append(it.name).append(".fromMapList(map['").append(it.value).append("']);")
        }

        /* map.value 转换为基础类型 list start **/
        if (listBaseList.isNotEmpty())
            sb.append("\n")
        for ((count, pair) in listBaseList.withIndex()) {
            sb.append("\n").append(tempSpaceStr).append("List dynamicList").append(count).append(" = map['").append(pair.value).append("'] ?? [];")
            sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(pair.value).append(" = new List();")

            var function = "o.toString()"
            when (pair.name) {
                "List" -> function = "int.parse(o.toString())"
                "List" -> function = "double.parse(o.toString())"
                "List" -> function = "o.toString() == 'true'"
            }

            sb.append("\n").append(tempSpaceStr).append(fieldName).append(".").append(pair.value).append(".addAll(dynamicList").append(count).append(".map((o) => ").append(function).append("));")
            sb.append("\n")
        }
        /* map.value 转换为基础类型 list end **/

        sb.append("\n").append(tempSpaceStr).append("return ").append(fieldName).append(";\n")
        sb.append(spaceStr).append("}\n")
        /* map.value 转换为对象的静态函数 end **/

        /* map.value 转换为 list 的静态函数 start **/
        sb.append("\n").append(spaceStr)
                .append("static ").append("List<").append(className).append(">").append(" fromMapList").append("(dynamic mapList) {")
                .append("\n").append(tempSpaceStr).append("if (mapList == null) return [];")
                .append("\n").append(tempSpaceStr).append("List<").append(className).append("> list = new List(mapList.length);")
                .append("\n").append(tempSpaceStr).append("for (int i = 0; i 
            printClassWithParams(value, space + 2, key)
        }

        val commentString = if (commentSb.toString().isBlank() || commentSb.isEmpty()) {
            ""
        } else {
            "\n$spaceStr/**\n$commentSb$spaceStr */\n\n"
        }

        return "$commentString$sb"
    }

    private fun buildClasses(): String {
        val sb = StringBuilder()

        // 开始定义类
        classes.forEach { key, value ->
            sb.append("\n")
                    .append("class").append(" ").append(key).append(" ").append("{").append("\n")
                    .append(printClassWithParams(value, 2, key))
                    .append("}").append("\n")
        }

        return sb.toString()
    }
}

他的

class ClassGenerator {
    val classes = mutableMapOf>()

    fun generate(name: String, jsonText: String): String {
        return try {

            val fields = Param.json2Params(JsonParser().parse(jsonText).asJsonObject)
            "class $name {\n${printClassWithParams(fields, 2, name)}\n}\n${buildClasses()}"
        } catch (jsonParseException: JsonParseException) {
            jsonParseException.printStackTrace()
            "error: not supported json"
        } catch (illegalStateException: IllegalStateException) {
            illegalStateException.printStackTrace()

            if (illegalStateException.message?.startsWith("Not a JSON Object") == true) {
                "error: not supported json"
            } else {
                "error: unknown"
            }
        }
    }

    fun generate(name: String, fields: JsonObject): String {
        return try {
            "class $name {\n${printClassWithParams(Param.json2Params(fields), 2, name)}\n}\n${buildClasses()}"
        } catch (jsonParseException: JsonParseException) {
            jsonParseException.printStackTrace()
            "error: not supported json"
        } catch (illegalStateException: IllegalStateException) {
            illegalStateException.printStackTrace()

            if (illegalStateException.message?.startsWith("Not a JSON Object") == true) {
                "error: not supported json"
            } else {
                "error: unknown"
            }
        }
    }

    private fun printClassWithParams(params: List, space: Int, className: String): String {
        val sb = StringBuilder()

        val tempClasses = HashMap>()

        var spaceStr = ""
        repeat(space) { spaceStr += " " }

        val orderedList = params
                .filter { it.key == "String" || it.key == "int" || it.key == "double" || it.key == "bool" || it.key == "num" }
                .sortedBy { it.key }
                .map {
                    sb.append("$spaceStr${it.key} ${it.camelWord};\n")
                    NameValuePair(it.value, it.camelWord)
                }

        val objectList = params
                .filter { it.key == "object" }
                .sortedBy { it.value }
                .map {
                    val clazzName = Utils.toUpperCaseFirstOne(it.value + "Bean")
                    classes[clazzName] = it.clazz
                    tempClasses[clazzName] = it.clazz
                    sb.append(spaceStr).append(clazzName).append(" ").append(it.camelWord).append(";").append("\n")
                    NamePair(it.camelWord, clazzName, it.value)
                }

        val listBaseList = params
                .filter { it.key.startsWith("List<") }
                .sortedBy { it.value }
                .map {
                    sb.append(spaceStr).append(it.key).append(" ").append(it.camelWord).append(";").append("\n")
                    NamePair(it.camelWord, it.key, it.value)
                }

        val listList = params
                .filter { "list" == it.key }
                .sortedBy { it.value }
                .map {
                    val clazzName = Utils.toUpperCaseFirstOne(it.value + "ListBean")
                    classes[clazzName] = it.clazz
                    tempClasses[clazzName] = it.clazz
                    sb.append(spaceStr).append("List<").append(clazzName).append(">").append(" ").append(it.camelWord).append(";").append("\n")
                    NamePair(it.camelWord, clazzName, it.value)
                }

        val tempSpaceStr = "$spaceStr  "


        /**
         * 构造
         */
        sb.append("\n").append(spaceStr)
                .append(className).append("({")

        orderedList.forEach {
            sb.append("this").append(".").append(it.value)
            sb.append(", ")
        }

        objectList.forEach {
            sb.append("this").append(".").append(it.camelKey)
            sb.append(", ")
        }

        listList.forEach {
            sb.append("this").append(".").append(it.camelKey)
            sb.append(", ")
        }

        listBaseList.forEach {
            sb.append("this").append(".").append(it.camelKey)
            sb.append(", ")
        }
        if (sb.endsWith(", ")) {
            sb.delete(sb.lastIndexOf(", "), sb.length)
        }
        sb.append("});\n")


        sb.append("\n").append(spaceStr)
                .append(className).append(".fromJson").append("(Map json) {")
                .append(tempSpaceStr)

        orderedList.forEach {
            sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.value).append(" = ").append("json['").append(it.name).append("'];")
        }

        objectList.forEach {
            sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.camelKey).append(" = ").append("json['").append(it.value).append("'] != null? ").append(it.key).append(".fromJson(json['").append(it.value).append("']) : null;")
        }

        listList.forEach {
            sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.camelKey).append(" = ").append("(json['").append(it.value).append("'] as List)!=null?(json['").append(it.value).append("'] as List).map((i) => ").append(it.key).append(".fromJson(i)).toList():null;")
        }

        listBaseList.forEach {
            sb.append("\n")
            sb.append("\n").append(tempSpaceStr).append("List ").append(it.camelKey).append("List").append(" = json['").append(it.value).append("'];")
            sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.camelKey).append(" = new List();")

            var function = "o.toString()"
            when (it.key) {
                "List" -> function = "int.parse(o.toString())"
                "List" -> function = "double.parse(o.toString())"
                "List" -> function = "o.toString() == 'true'"
            }

            sb.append("\n").append(tempSpaceStr).append("this").append(".").append(it.camelKey).append(".addAll(").append(it.camelKey).append("List").append(".map((o) => ").append(function).append("));")
        }

        sb.append("\n").append(spaceStr).append("}\n\n")

        sb.append(spaceStr)
                .append("Map toJson() {\n").append(tempSpaceStr).append("final Map data = new Map();")
        orderedList.forEach {
            sb.append("\n").append(tempSpaceStr).append("data['").append(it.name).append("'] = ").append("this").append(".").append(it.value).append(";")
        }

        objectList.forEach {
            sb.append("\n").append(tempSpaceStr).append("data['").append(it.value).append("'] = ").append("this").append(".").append(it.camelKey).append(".toJson();")
        }

        listList.forEach {
            sb.append("\n").append(tempSpaceStr).append("data['").append(it.value).append("'] = ").append("this").append(".").append(it.camelKey).append(" != null?this.").append(it.camelKey).append(".map((i) => i.toJson()).toList():null;")
        }

        listBaseList.forEach {
            sb.append("\n").append(tempSpaceStr).append("data['").append(it.value).append("'] = ").append("this").append(".").append(it.camelKey).append(";")
        }

        sb.append("\n").append(tempSpaceStr).append("return data;\n")
        sb.append(spaceStr).append("}\n")


        tempClasses.forEach { key, value ->
            printClassWithParams(value, space + 2, key)
        }

        return sb.toString()
    }

    private fun buildClasses(): String {
        val sb = StringBuilder()

        classes.forEach { key, value ->
            sb.append("\n")
                    .append("class").append(" ").append(key).append(" ").append("{").append("\n")
                    .append(printClassWithParams(value, 2, key))
                    .append("}").append("\n")
        }

        return sb.toString()
    }
}

是不是一个模子刻出来的?大量的函数名、属性名都是一致的,换行空行也都是一致的

NameValuePair/NamePair

我的

由于我已经将 NameValuePair 用 kotlin 改写了,下面的代码是从 git 提交记录里找到的

/**
 * Created by zhangll on 2018/8/3.
 */
public class NameValuePair {
    String name;
    String value;

    public NameValuePair(String name, String value) {
        this.name = name;
        this.value = value;
    }
}

他的

public class NamePair {
    private String camelKey;
    private String key;
    private String value;

    public NamePair(String camelKey, String key, String value) {
        this.camelKey = camelKey;
        this.key = key;
        this.value = value;
    }

    public String getCamelKey() {
        return camelKey;
    }

    public void setCamelKey(String camelKey) {
        this.camelKey = camelKey;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

乍一看似乎不一样,其实他只是多写了 getter setter,又加了一个驼峰命名功能的字段。我怎么看出来一致的呢?因为 NameValuePair 严格来说,就应该给属性命名 name 和 value。而另一个人的类名叫 NamePair,中间偏偏少了个 Value ,属性命名却又是 key(不是理论上的 name)、value,这是为什么呢?明眼人应该一看就知道了。

Param

我的

/**
 * Created by zhangll on 2018/8/3.
 */
public class Param {
    String key;
    String value;
    List clazz;
    String comment;

    /**
     *
     * @param key 变量名
     * @param object 变量内容
     * @return
     */
    public static Param makeParam(String key, Object object) {
        if (object == null || "null".equals(object.toString())) {
            return new Param("dynamic", key, null, object);
        }

        if (object instanceof JsonObject) {
            JsonObject jsOnObject= (JsonObject) object;
            return new Param("object", key, json2Params(jsonObject), jsonObject);
        } else if (object instanceof JsonArray) {
            JsonArray jsOnArray= (JsonArray) object;
            if (jsonArray.size() != 0) {
                Object obj = jsonArray.get(0);
                if (obj instanceof JsonObject) {
                    return new Param("list", key, json2Params(jsonArray.get(0).getAsJsonObject()), jsonArray);
                } else if (obj instanceof JsonArray) {
                    return new Param("dynamicList", key, null, object);
                } else {
                    Param temp = makeParam("placeholder", obj);
                    if (temp.key.equals("dynamic")) {
                        return new Param("dynamicList", key, null, object);
                    }
                    return new Param("List<" + temp.key + ">", key, null, object);
                }
            } else {
                return new Param("dynamicList", key, null, object);
            }
        } else if (tryParseBoolean(object)) {
            return new Param("bool", key, null, "true".equals(object.toString()));
        } else if (tryParseInt(object)) {
            return new Param("int", key, null, Integer.parseInt(object.toString()));
        } else if (tryParseLong(object)) {
            return new Param("int", key, null, Long.parseLong(object.toString()));
        } else if (tryParseDouble(object)) {
            return new Param("double", key, null, Double.parseDouble(object.toString()));
        } else if (tryParseFloat(object)) {
            return new Param("double", key, null, Float.parseFloat(object.toString()));
        } else {
            return new Param("String", key, null, object.toString());
        }
    }

    public static List json2Params(JsonObject jsonObject) {
        List list = new ArrayList<>();
        for (Object o : jsonObject.entrySet()) {
            Map.Entry entry = (Map.Entry) o;
            list.add(Param.makeParam(entry.getKey().toString(), entry.getValue()));
        }

        return list;
    }

    private static boolean tryParseInt(Object object) {
        try {
            int i = Integer.parseInt(object.toString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean tryParseLong(Object object) {
        try {
            long i = Long.parseLong(object.toString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean tryParseDouble(Object object) {
        try {
            double d = Double.parseDouble(object.toString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean tryParseFloat(Object object) {
        try {
            float f = Float.parseFloat(object.toString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean tryParseBoolean(Object object) {
        String b = object.toString();
        return Objects.equals(b, "true") || Objects.equals(b, "false");
    }

    public Param(String key, String value, List clazz, Object content) {
        this.key = key;
        this.value = value;
        this.clazz = clazz;

        if (cOntent== null) return;

        // 注释处理
        this.comment = value + " : " + content.toString().replaceAll("\n", "");
    }

    @Override
    public String toString() {
        return "Param{" +
                "key='" + key + '\'' +
                ", value='" + value + '\'' +
                ", classes=" + clazz +
                '}';
    }
}

他的

public class Param {
    String key;
    String value;
    String camelWord;
    List clazz;

    /**
     *
     * @param key 变量名
     * @param object 变量内容
     * @return
     */
    public static Param makeParam(String key, Object object) {
        if (object instanceof JsonObject) {
            JsonObject jsOnObject= (JsonObject) object;
            return new Param("object", key, json2Params(jsonObject));
        } else if (object instanceof JsonArray) {
            JsonArray jsOnArray= (JsonArray) object;
            if (jsonArray.size() != 0) {
                Object obj = jsonArray.get(0);
                if (obj instanceof JsonObject) {
                    return new Param("list", key, json2Params(jsonArray.get(0).getAsJsonObject()));
                } else {
                    Param temp = makeParam("placeholder", obj);
                    return new Param("List<" + temp.key + ">", key, null);
                }
            } else {
                return new Param("list", key, null);
            }
        } else if (tryParseBoolean(object)) {
            return new Param("bool", key, null);
        } else if (tryParseInt(object)) {
            return new Param("int", key, null);
        } else if (tryParseLong(object)) {
            return new Param("num", key, null);
        } else if (tryParseDouble(object)) {
            return new Param("double", key, null);
        } else if (tryParseFloat(object)) {
            return new Param("double", key, null);
        } else {
            return new Param("String", key, null);
        }
    }

    public static List json2Params(JsonObject jsonObject) {
        List list = new ArrayList<>();
        for (Object o : jsonObject.entrySet()) {
            Map.Entry entry = (Map.Entry) o;
            list.add(Param.makeParam(entry.getKey().toString(), entry.getValue()));
        }

        return list;
    }

    private static boolean tryParseInt(Object object) {
        try {
            int i = Integer.parseInt(object.toString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean tryParseLong(Object object) {
        try {
            long i = Long.parseLong(object.toString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean tryParseDouble(Object object) {
        try {
            double d = Double.parseDouble(object.toString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean tryParseFloat(Object object) {
        try {
            float f = Float.parseFloat(object.toString());
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean tryParseBoolean(Object object) {
        String b = object.toString();
        return Objects.equals(b, "true") || Objects.equals(b, "false");
    }

    public Param(String key, String value, List clazz) {
        this.key = key;
        this.value = value;
        this.camelWord = Utils.toUpperCaseParams(value);
        this.clazz = clazz;
    }

    @Override
    public String toString() {
        return "Param{" +
                "key='" + key + '\'' +
                ", value='" + value + '\'' +
                ", classes=" + clazz +
                '}';
    }
}

又是一个模子刻出来的。除了我新增了注释功能和部分 bug 修复导致的代码变动,他新增了驼峰命名功能。

Util/Utils

我的

/**
 * Created by zhangll on 2018/8/3.
 */
public class Util {
    /**
     * 将字符串复制到剪切板。
     */
    public static void setSysClipboardText(String writeMe) {
        Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
        Transferable tText = new StringSelection(writeMe);
        clip.setContents(tText, null);
    }

    // 首字母转大写
    public static String toUpperCaseFirstOne(String s){
        if(Character.isUpperCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    // 首字母转小写
    public static String toLowerCaseFirstOne(String s){
        if(Character.isLowerCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    // 将 string 写入文件
    public static void writeToFile(Project project, VirtualFile file, String content) {
        Runnable runnable = () -> {
            try {
                file.setBinaryContent(content.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        };

        WriteCommandAction.runWriteCommandAction(project, runnable);
    }
}

他的

public class Utils {
    /**
     * 将字符串复制到剪切板。
     */
    public static void setSysClipboardText(String writeMe) {
        Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard();
        Transferable tText = new StringSelection(writeMe);
        clip.setContents(tText, null);
    }

    // 首字母转大写
    public static String toUpperCaseFirstOne(String s) {
        if (s.contains("_")) {
            String[] a = s.split("_");
            StringBuilder builder = new StringBuilder();
            for (String anA : a) {
                if (Character.isUpperCase(anA.charAt(0)))
                    builder.append(anA);
                else
                    builder.append(Character.toUpperCase(anA.charAt(0))).append(anA.substring(1));
            }
            return builder.toString();
        }
        if (Character.isUpperCase(s.charAt(0)))
            return s;
        else
            return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
    }

    // 下划线参数转驼峰
    public static String toUpperCaseParams(String s) {
        if (s.contains("_")) {
            String[] a = s.split("_");
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i  
 

写文件的代码好像有不同?没关系,我 git 里拉老代码出来

// 将 string 写入文件
public static void writeToFile(VirtualFile file, String content) {
    try {
        file.setBinaryContent(content.getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

所以,唯一的不同就是我类头有注释,而他多了一个驼峰命名的方法。

放上另一个人的项目地址,有闲心的朋友可以自己去看

github.com/xlyasdasd/F…

总结一下

如果就 copy 一下我的代码过去用,其实我肯定也没什么,按道理来说作为一个程序猿我还应该觉得开心才是。

但是 copy 了我整个项目,又极其不专业的只改了几个不痛不痒的地方,改得此地无银三百两,留着项目结构、类命名、方法命名、空行、换行这些个人风格浓重的东西不动,我是 Kotlin 写的地方他就是 Kotlin,我用 Java 写的地方他就是 Java, 难道是因为核心逻辑看不懂不敢改动吗?既然能自己加上驼峰命名的功能,想来也不至于。

如果只是 copy 项目也就罢了,他甚至还发布到了全家桶插件的官网,如果不是因为下载量比我自己的插件还高,恐怕这事我到死都不会知道。

当然,他没什么错,是我自己没给开源项目加上 LICENSE。但想来就算我有 LICENSE,按他能去发布插件这个勇气来看,只怕也是不在乎的。

有朋友跟我说,我应该开心,应该有成就感,因为至少这证明我做的东西是有价值的,但我觉得事情不应该这么去看待。我花了心思去写出来的东西,我心肝情愿的开源,我心肝情愿的给别人用,但是拿了我的心血去换个包装贴上他自己的牌子,这谁能接受?

作为一个喜欢 flutter 的开发者,我也不至于因为这事就丧了气,尽管也付出了不少时间,做了不少迭代,但毕竟只是一个小玩具项目而已。只是这次被好好的上了一课,以后不论多小的项目,LICENSE 是一定不能少的。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 我们


推荐阅读
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • 包含phppdoerrorcode的词条 ... [详细]
  • MySQL初级篇——字符串、日期时间、流程控制函数的相关应用
    文章目录:1.字符串函数2.日期时间函数2.1获取日期时间2.2日期与时间戳的转换2.3获取年月日、时分秒、星期数、天数等函数2.4时间和秒钟的转换2. ... [详细]
  • C#实现文件的压缩与解压
    2019独角兽企业重金招聘Python工程师标准一、准备工作1、下载ICSharpCode.SharpZipLib.dll文件2、项目中引用这个dll二、文件压缩与解压共用类 ... [详细]
  • 本文详细介绍了 Spark 中的弹性分布式数据集(RDD)及其常见的操作方法,包括 union、intersection、cartesian、subtract、join、cogroup 等转换操作,以及 count、collect、reduce、take、foreach、first、saveAsTextFile 等行动操作。 ... [详细]
  • Android 自定义 RecycleView 左滑上下分层示例代码
    为了满足项目需求,需要在多个场景中实现左滑删除功能,并且后续可能在列表项中增加其他功能。虽然网络上有很多左滑删除的示例,但大多数封装不够完善。因此,我们尝试自己封装一个更加灵活和通用的解决方案。 ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • 本文将带你快速了解 SpringMVC 框架的基本使用方法,通过实现一个简单的 Controller 并在浏览器中访问,展示 SpringMVC 的强大与简便。 ... [详细]
  • com.sun.javadoc.PackageDoc.exceptions()方法的使用及代码示例 ... [详细]
  • 在多线程并发环境中,普通变量的操作往往是线程不安全的。本文通过一个简单的例子,展示了如何使用 AtomicInteger 类及其核心的 CAS 无锁算法来保证线程安全。 ... [详细]
  • 本教程详细介绍了如何使用 Spring Boot 创建一个简单的 Hello World 应用程序。适合初学者快速上手。 ... [详细]
author-avatar
cb风雨彩虹
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有