安卓编写区块链的尝试(失败)

这篇具有很好参考价值的文章主要介绍了安卓编写区块链的尝试(失败)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

@Data

public class Block {

/**

  • 区块hash值

*/

private String hash;

/**

  • 前一个区块的hash值

*/

private String prevBlockHash;

/**

  • 区块交易

*/

private List transactions;

/**

  • 时间戳,单位秒

*/

private long timeStamp;

/**

  • 区块的高度

*/

private long height;

/**

  • 工作量证明计数器

*/

private long nonce;

/**

  • 创建新的区块

  • @param previousHash

  • @param transactions

  • @return

*/

public static Block newBlock(String previousHash, List transactions, long height) {

Block block = new Block(“”, previousHash, transactions, Instant.now().getEpochSecond(),height,0);

ProofOfWork pow = ProofOfWork.newProofOfWork(block);

PowResult powResult = pow.run();

block.setHash(powResult.getHash());

block.setNonce(powResult.getNonce());

// block.setHash();

return block;

}

private static final String ZERO_HASH = Hex.encodeHexString(new byte[32]);

/**

  • 创建创世区块

  • @param coinbase

  • @return

*/

public static Block newGenesisBlock(Transaction coinbase) {

List transactions = new ArrayList<>();

transactions.add(coinbase);

return Block.newBlock(ByteUtils.ZERO_HASH, transactions,0);

}

/**

  • 对区块中的交易信息进行Hash计算

  • @return

*/

public byte[] hashTransaction() {

byte[][] txIdArrays = new byte[this.getTransactions().size()][];

for (int i = 0; i < this.getTransactions().size(); i++) {

txIdArrays[i] = this.getTransactions().get(i).getTxId();

}

return DigestUtils.sha256(ByteUtils.merge(txIdArrays));

}

}

创建ByteUtils.java

该类的作用是将数据转换承byte[]字节数据

package com.example.blockchain;

import org.apache.commons.codec.binary.Hex;

import org.apache.commons.lang3.ArrayUtils;

import java.nio.ByteBuffer;

import java.util.Arrays;

import java.util.stream.Stream;

/**

  • 字节数组工具类

*/

public class ByteUtils {

public static final String ZERO_HASH = Hex.encodeHexString(new byte[32]);

/**

  • 将多个字节数组合并成一个字节数组

  • @param bytes

  • @return

*/

public static byte[] merge(byte[]… bytes) {

Stream stream = Stream.of();

for (byte[] b : bytes) {

stream = Stream.concat(stream, Arrays.stream(ArrayUtils.toObject(b)));

}

return ArrayUtils.toPrimitive(stream.toArray(Byte[]::new));

}

/**

  • long 转化为 byte[]

  • @param val

  • @return

*/

public static byte[] toBytes(long val) {

return ByteBuffer.allocate(Long.BYTES).putLong(val).array();

}

}

创建Blockchain.java

其中的方法有创建区块链,添加区块Block,区块链遍历,打包交易信息创建区块添加到区块链等

package com.example.blockchain;

import org.apache.commons.codec.binary.Hex;

import org.apache.commons.lang3.ArrayUtils;

import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import lombok.AllArgsConstructor;

import lombok.Data;

/**

  • 区块链

*/

@Data

@AllArgsConstructor

public class Blockchain {

/**

  • 最后一个区块的hash

*/

private String lastBlockHash;

/**

  • 创建区块链,createBlockchain

  • @param address

  • @return

*/

public static Blockchain createBlockchain(String address) {

String lastBlockHash = “”;

if (StringUtils.isBlank(lastBlockHash)){

//对应的bucket不存在,说明是第一次获取区块链实例

// 创建 coinBase 交易

Transaction coinbaseTX = Transaction.newCoinbaseTX(address, “”);

Block genesisBlock = Block.newGenesisBlock(coinbaseTX);

lastBlockHash = genesisBlock.getHash();

RocksDBUtils.getInstance().putBlock(genesisBlock);

RocksDBUtils.getInstance().putLastBlockHash(lastBlockHash);

}

return new Blockchain(lastBlockHash);

}

/**

  • 根据block,添加区块

  • @param block

*/

public void addBlock(Block block) {

RocksDBUtils.getInstance().putLastBlockHash(block.getHash());

RocksDBUtils.getInstance().putBlock(block);

this.lastBlockHash = block.getHash();

}

/**

  • 根据data添加区块

  • @param data

*/

// public void addBlock(String data) throws Exception{

//

// String lastBlockHash = RocksDBUtils.getInstance().getLastBlockHash();

// if (StringUtils.isBlank(lastBlockHash)){

// throw new Exception(“还没有数据库,无法直接添加区块。。”);

// }

// this.addBlock(Block.newBlock(lastBlockHash,data));

// }

/**

  • 区块链迭代器:内部类

*/

public class BlockchainIterator{

/**

  • 当前区块的hash

*/

private String currentBlockHash;

/**

  • 构造函数

  • @param currentBlockHash

*/

public BlockchainIterator(String currentBlockHash) {

this.currentBlockHash = currentBlockHash;

}

/**

  • 判断是否有下一个区块

  • @return

*/

public boolean hashNext() {

if (ByteUtils.ZERO_HASH.equals(currentBlockHash)) {

return false;

}

Block lastBlock = RocksDBUtils.getInstance().getBlock(currentBlockHash);

if (lastBlock == null) {

return false;

}

// 如果是创世区块

if (ByteUtils.ZERO_HASH.equals(lastBlock.getPrevBlockHash())) {

return true;

}

return RocksDBUtils.getInstance().getBlock(lastBlock.getPrevBlockHash()) != null;

}

/**

  • 迭代获取区块

  • @return

*/

public Block next() {

Block currentBlock = RocksDBUtils.getInstance().getBlock(currentBlockHash);

if (currentBlock != null) {

this.currentBlockHash = currentBlock.getPrevBlockHash();

return currentBlock;

}

return null;

}

}

/**

  • 添加方法,用于获取迭代器实例

  • @return

*/

public BlockchainIterator getBlockchainIterator() {

return new BlockchainIterator(lastBlockHash);

}

/**

  • 打包交易,进行挖矿

  • @param transactions

*/

public void mineBlock(List transactions) throws Exception {

String lastBlockHash = RocksDBUtils.getInstance().getLastBlockHash();

Block lastBlock = RocksDBUtils.getInstance().getBlock(lastBlockHash);

if (lastBlockHash == null) {

throw new Exception("ERROR: Fail to get last block hash ! ");

}

Block block = Block.newBlock(lastBlockHash, transactions,lastBlock.getHeight()+1);

this.addBlock(block);

}

/**

  • 从交易输入中查询区块链中所有已被花费了的交易输出

  • @param address 钱包地址

  • @return 交易ID以及对应的交易输出下标地址

  • @throws Exception

*/

private Map<String, int[]> getAllSpentTXOs(String address) {

// 定义TxId ——> spentOutIndex[],存储交易ID与已被花费的交易输出数组索引值

Map<String, int[]> spentTXOs = new HashMap<>();

for (BlockchainIterator blockchainIterator = this.getBlockchainIterator(); blockchainIterator.hashNext(); ) {

Block block = blockchainIterator.next();

for (Transaction transaction : block.getTransactions()) {

// 如果是 coinbase 交易,直接跳过,因为它不存在引用前一个区块的交易输出

if (transaction.isCoinbase()) {

continue;

}

for (TXInput txInput : transaction.getInputs()) {

if (txInput.canUnlockOutputWith(address)) {

String inTxId = Hex.encodeHexString(txInput.getTxId());

int[] spentOutIndexArray = spentTXOs.get(inTxId);

if (spentOutIndexArray == null) {

spentTXOs.put(inTxId, new int[]{txInput.getTxOutputIndex()});

} else {

spentOutIndexArray = ArrayUtils.add(spentOutIndexArray, txInput.getTxOutputIndex());

spentTXOs.put(inTxId, spentOutIndexArray);

}

}

}

}

}

return spentTXOs;

}

/**

  • 查找钱包地址对应的所有未花费的交易

  • @param address 钱包地址

  • @return

*/

private Transaction[] findUnspentTransactions(String address) throws Exception {

Map<String, int[]> allSpentTXOs = this.getAllSpentTXOs(address);

Transaction[] unspentTxs = {};

// 再次遍历所有区块中的交易输出

for (BlockchainIterator blockchainIterator = this.getBlockchainIterator(); blockchainIterator.hashNext(); ) {

Block block = blockchainIterator.next();

for (Transaction transaction : block.getTransactions()) {

String txId = Hex.encodeHexString(transaction.getTxId());

int[] spentOutIndexArray = allSpentTXOs.get(txId);

for (int outIndex = 0; outIndex < transaction.getOutputs().length; outIndex++) {

if (spentOutIndexArray != null && ArrayUtils.contains(spentOutIndexArray, outIndex)) {

continue;

}

// 保存不存在 allSpentTXOs 中的交易

if (transaction.getOutputs()[outIndex].canBeUnlockedWith(address)) {

unspentTxs = ArrayUtils.add(unspentTxs, transaction);

}

}

}

}

return unspentTxs;

}

/**

  • 查找钱包地址对应的所有UTXO

  • @param address 钱包地址

  • @return

*/

public TXOutput[] findUTXO(String address) throws Exception {

Transaction[] unspentTxs = this.findUnspentTransactions(address);

TXOutput[] utxos = {};

if (unspentTxs == null || unspentTxs.length == 0) {

return utxos;

}

for (Transaction tx : unspentTxs) {

for (TXOutput txOutput : tx.getOutputs()) {

if (txOutput.canBeUnlockedWith(address)) {

utxos = ArrayUtils.add(utxos, txOutput);

}

}

}

return utxos;

}

/**

  • 寻找能够花费的交易

  • @param address 钱包地址

  • @param amount 花费金额

*/

public SpendableOutputResult findSpendableOutputs(String address, int amount) throws Exception {

Transaction[] unspentTXs = this.findUnspentTransactions(address);

int accumulated = 0;

Map<String, int[]> unspentOuts = new HashMap<>();

for (Transaction tx : unspentTXs) {

String txId = Hex.encodeHexString(tx.getTxId());

for (int outId = 0; outId < tx.getOutputs().length; outId++) {

TXOutput txOutput = tx.getOutputs()[outId];

if (txOutput.canBeUnlockedWith(address) && accumulated < amount) {

accumulated += txOutput.getValue();

int[] outIds = unspentOuts.get(txId);

if (outIds == null) {

outIds = new int[]{outId};

} else {

outIds = ArrayUtils.add(outIds, outId);

}

unspentOuts.put(txId, outIds);

if (accumulated >= amount) {

break;

}

}

}

}

return new SpendableOutputResult(accumulated, unspentOuts);

}

/**

  • 从 DB 从恢复区块链数据

  • @return

  • @throws Exception

*/

public static Blockchain initBlockchainFromDB() throws Exception {

String lastBlockHash = RocksDBUtils.getInstance().getLastBlockHash();

if (lastBlockHash == null) {

throw new Exception("ERROR: Fail to init blockchain from db. ");

}

return new Blockchain(lastBlockHash);

}

}

创建ProofOfWork.java(工作量证明)

工作量证明是经过困难的工作,将数据放入区块链中,这样别人就不太可能取修改区块链中的区块,想要修改其中一个块,必须经过大量计算,还要计算这个块之后的块

这里将计算难度设置为16,就是根据nonce计算出来的hash前16位必须为0,这样才能比目标值小,这样添加的区块才能被认可

package com.example.blockchain;

import org.apache.commons.codec.digest.DigestUtils;

import org.apache.commons.lang3.StringUtils;

import java.math.BigInteger;

import lombok.AllArgsConstructor;

import lombok.Data;

/**

  • 工作量证明

  • @author hanru

*/

@Data

@AllArgsConstructor

public class ProofOfWork {

/**

  • 难度目标位

  • 0000 0000 0000 0000 1001 0001 0000 … 0001

  • 256位Hash里面前面至少有16个零

*/

public static final int TARGET_BITS = 16;

/**

  • 要验证的区块

*/

private Block block;

/**

  • 难度目标值

*/

private BigInteger target;

/**

  • 创建新的工作量证明对象

  • 对1进行移位运算,将1向左移动 (256 - TARGET_BITS) 位,得到我们的难度目标值

  • @param block

  • @return

*/

public static ProofOfWork newProofOfWork(Block block) {

/*

1.创建一个BigInteger的数值1.

0000000…00001

2.左移256-bits位

以8 bit为例

0000 0001

0010 0000

8-6

*/

BigInteger targetValue = BigInteger.ONE.shiftLeft((256 - TARGET_BITS));

return new ProofOfWork(block, targetValue);

}

/**

  • 运行工作量证明,开始挖矿,找到小于难度目标值的Hash

  • @return

*/

public PowResult run() {

long nonce = 0;

String shaHex = “”;

// System.out.printf(“开始进行挖矿:%s \n”, this.getBlock().getData());

System.out.printf(“开始进行挖矿: \n”);

long startTime = System.currentTimeMillis();

while (nonce < Long.MAX_VALUE) {

byte[] data = this.prepareData(nonce);

shaHex = DigestUtils.sha256Hex(data);

System.out.printf(“\r%d: %s”,nonce,shaHex);

if (new BigInteger(shaHex, 16).compareTo(this.target) == -1) {

System.out.println();

System.out.printf(“耗时 Time: %s seconds \n”, (float) (System.currentTimeMillis() - startTime) / 1000);

System.out.printf(“当前区块Hash: %s \n\n”, shaHex);

break;

} else {

nonce++;

}

}

return new PowResult(nonce, shaHex);

}

/**

  • 根据block的数据,以及nonce,生成一个byte数组

  • 注意:在准备区块数据时,一定要从原始数据类型转化为byte[],不能直接从字符串进行转换

  • @param nonce

  • @return

*/

private byte[] prepareData(long nonce) {

byte[] prevBlockHashBytes = {};

if (StringUtils.isNoneBlank(this.getBlock().getPrevBlockHash())) {

prevBlockHashBytes = new BigInteger(this.getBlock().getPrevBlockHash(), 16).toByteArray();

}

return ByteUtils.merge(

prevBlockHashBytes,

// this.getBlock().getData().getBytes(),

this.getBlock().hashTransaction(),

ByteUtils.toBytes(this.getBlock().getTimeStamp()),

ByteUtils.toBytes(TARGET_BITS),

ByteUtils.toBytes(nonce)

);

}

/**

  • 验证区块是否有效

  • @return

*/

public boolean validate() {

byte[] data = this.prepareData(this.getBlock().getNonce());

return new BigInteger(DigestUtils.sha256Hex(data), 16).compareTo(this.target) == -1;

}

}

创建TXInput.java(交易中的输入)

package com.example.blockchain;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

@AllArgsConstructor

@NoArgsConstructor

@Data

public class TXInput {

/**

  • txId是前一次交易的ID

*/

private byte[] txId;

/**

  • 交易输出索引

*/

private int txOutputIndex;

/**

  • 解锁脚本

*/

private String scriptSig;

/**

  • 判断解锁数据是否能够解锁交易输出

  • @param unlockingData

  • @return

*/

public boolean canUnlockOutputWith(String unlockingData) {

return this.getScriptSig().endsWith(unlockingData);

}

}

创建TXOutput.java(交易中的输出)

package com.example.blockchain;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

/**

  • @author hanru

*/

@Data

@AllArgsConstructor

@NoArgsConstructor

public class TXOutput {

/**

  • 数值金额

*/

private int value;

/**

  • 锁定脚本

*/

private String scriptPubKey;

/**

  • 判断解锁数据是否能够解锁交易输出

  • @param unlockingData

  • @return

*/

public boolean canBeUnlockedWith(String unlockingData) {

return this.getScriptPubKey().endsWith(unlockingData);

}

}

创建 Transaction.java

package com.example.blockchain;

import org.apache.commons.codec.binary.Hex;

import org.apache.commons.codec.digest.DigestUtils;

import org.apache.commons.lang3.ArrayUtils;

import org.apache.commons.lang3.StringUtils;

import java.util.Iterator;

import java.util.Map;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

@Data

@AllArgsConstructor

@NoArgsConstructor

public class Transaction {

private static final int SUBSIDY = 10;

/**

  • 交易的Hash

*/

private byte[] txId;

/**

  • 交易输入

*/

private TXInput[] inputs;

/**

  • 交易输出

*/

private TXOutput[] outputs;

/**

  • 设置交易ID

*/

private void setTxId() {

this.setTxId(DigestUtils.sha256(SerializeUtils.serialize(this)));

}

/**

  • 创建CoinBase交易

  • @param to 收账的钱包地址

  • @param data 解锁脚本数据

  • @return

*/

public static Transaction newCoinbaseTX(String to, String data) {

if (StringUtils.isBlank(data)) {

data = String.format(“Reward to ‘%s’”, to);

}

// 创建交易输入

TXInput txInput = new TXInput(new byte[]{}, -1, data);

// 创建交易输出

TXOutput txOutput = new TXOutput(SUBSIDY, to);

// 创建交易

Transaction tx = new Transaction(null, new TXInput[]{txInput}, new TXOutput[]{txOutput});

// 设置交易ID

tx.setTxId();

return tx;

}

/**

  • 从 from 向 to 支付一定的 amount 的金额

  • @param from 支付钱包地址

  • @param to 收款钱包地址

  • @param amount 交易金额

  • @param blockchain 区块链

  • @return

*/

public static Transaction newUTXOTransaction(String from, String to, int amount, Blockchain blockchain) throws Exception {

SpendableOutputResult result = blockchain.findSpendableOutputs(from, amount);

int accumulated = result.getAccumulated();

Map<String, int[]> unspentOuts = result.getUnspentOuts();

if (accumulated < amount) {

throw new Exception(“ERROR: Not enough funds”);

}

Iterator<Map.Entry<String, int[]>> iterator = unspentOuts.entrySet().iterator();

TXInput[] txInputs = {};

while (iterator.hasNext()) {

Map.Entry<String, int[]> entry = iterator.next();

String txIdStr = entry.getKey();

int[] outIdxs = entry.getValue();

byte[] txId = Hex.decodeHex(txIdStr.toCharArray());

for (int outIndex : outIdxs) {

txInputs = ArrayUtils.add(txInputs, new TXInput(txId, outIndex, from));

}

}

TXOutput[] txOutput = {};

txOutput = ArrayUtils.add(txOutput, new TXOutput(amount, to));

if (accumulated > amount) {

txOutput = ArrayUtils.add(txOutput, new TXOutput((accumulated - amount), from));
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

安卓编写区块链的尝试(失败),程序员,android,区块链

安卓编写区块链的尝试(失败),程序员,android,区块链

安卓编写区块链的尝试(失败),程序员,android,区块链

安卓编写区块链的尝试(失败),程序员,android,区块链

安卓编写区块链的尝试(失败),程序员,android,区块链

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

安卓编写区块链的尝试(失败),程序员,android,区块链

总结

其实要轻松掌握很简单,要点就两个:

  1. 找到一套好的视频资料,紧跟大牛梳理好的知识框架进行学习。
  2. 多练。 (视频优势是互动感强,容易集中注意力)

你不需要是天才,也不需要具备强悍的天赋,只要做到这两点,短期内成功的概率是非常高的。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

以上就是总结的关于在面试的一些总结,希望对大家能有些帮助,除了这些面试中需要注意的问题,当然最重要的就是刷题了,这里放上我之前整理的一份超全的面试专题PDF

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

安卓编写区块链的尝试(失败),程序员,android,区块链

这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~文章来源地址https://www.toymoban.com/news/detail-846472.html

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

utput(amount, to));

if (accumulated > amount) {

txOutput = ArrayUtils.add(txOutput, new TXOutput((accumulated - amount), from));
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-Yc9Wxd5c-1712402146838)]

[外链图片转存中…(img-eyoPVLbA-1712402146838)]

[外链图片转存中…(img-K4HP3SsA-1712402146839)]

[外链图片转存中…(img-MijjiDRV-1712402146839)]

[外链图片转存中…(img-RB7XUtLr-1712402146839)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

安卓编写区块链的尝试(失败),程序员,android,区块链

总结

其实要轻松掌握很简单,要点就两个:

  1. 找到一套好的视频资料,紧跟大牛梳理好的知识框架进行学习。
  2. 多练。 (视频优势是互动感强,容易集中注意力)

你不需要是天才,也不需要具备强悍的天赋,只要做到这两点,短期内成功的概率是非常高的。

对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。

以上就是总结的关于在面试的一些总结,希望对大家能有些帮助,除了这些面试中需要注意的问题,当然最重要的就是刷题了,这里放上我之前整理的一份超全的面试专题PDF

还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

[外链图片转存中…(img-mkDqRGPF-1712402146839)]

这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

到了这里,关于安卓编写区块链的尝试(失败)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Kali中搭建vulhub时镜像git失败_vulhub git,每个程序员都必须掌握的8种数据结构

    先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7 深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前! 因此收集整理了一份《2024年最新网络安全全套学习资料》

    2024年04月27日
    浏览(49)
  • 【Android 逆向】程序员高危开发方向 ( 违法软件类型 | 赌博游戏 | 色情类应用 | 涉及金融类软件 | 爬虫类软件 | 区块链货币 | 甄别是否合法 )

    棋牌类 游戏开发 , 写这类游戏的程序员 很容易被抓 , 只要 涉及到了 充值 以及 提现 , 就是涉嫌赌博 ; 常见的 就是 麻将类游戏 , 纸牌类游戏 , 具体的地方麻将或扑克玩法 , 德州扑克 , 21 点 , 老虎机 等 类型的 游戏 ; 抽卡类的游戏 , 充值 然后 赌概率 , 比如原神这种 , 只充值

    2024年01月19日
    浏览(45)
  • 程序员简历程序员简历.pdf

    你们在制作简历时,是不是基本只关注两件事: 简历模板,还有基本信息的填写 。 当你再次坐下来更新你的简历时,可能会发现自己不自觉地选择了那个“ 看起来最好看的模板 ”,填写基本信息,却没有深入思考如何使简历更具吸引力。这其实是一个普遍现象: 许多求职

    2024年04月14日
    浏览(49)
  • AI程序员对程序员的影响

    最近,全球首位AI程序员Devin的出现引发了广泛关注,也引发了人们对人工智能在编程领域的潜力和影响的讨论。尽管AI技术在编程领域得到广泛应用,但人们仍然在探讨它是否能完全取代人类程序员。本文将探讨AI程序员的优势、局限性以及对程序员职业的影响,并展望未来

    2024年03月23日
    浏览(59)
  • 普通程序员和厉害程序员的差距!

    大家好,我是 程序员陶朱公 。 今天跟大家聊一下关于代码重构的话题。 话说,很多程序员对自己写的代码平时很随心所欲(各种魔法变量,一个方法几十上百行代码,还有各种让人崩溃的变量或方法命名)。 当有一天让他维护他人的代码,他就会抓狂,很容易激发他体内重构

    2024年03月23日
    浏览(64)
  • 大批程序员失业,大龄程序员出路在哪里?

    在程序员这个群体中,时常有人陷入技术迷信和思维僵化的困境,但实际上,当前市场对于技术的需求是非常广泛的。因此,我提出了一些建议,希望能够帮助程序员跳出技术框架,更好地利用技能创造实际价值。以下是一些建议供参考: 开发小而实用的工具类软件: 以“

    2024年01月22日
    浏览(56)
  • 低代码——面向程序员,帮助程序员敏捷开发

    低代码是一套可视化开发工具,它帮开发者把前后端基础功能写扎实,开发者只需要 通过填表配置或拖拽生成前端组件 的方式,即可完成后台管理系统的快速搭建。由于低代码仍需要 写少量 JS 代码 ,所以低代码开发平台主要面向程序员,帮助程序员敏捷开发。 本文使用

    2024年02月01日
    浏览(51)
  • 专科程序员与本科程序员之间有什么区别?

    专科程序员和本科程序员之间最主要的区别在于他们的学历水平以及所接受的教育和培训的深度和广度不同。 本科程序员通常拥有更为全面的计算机技术理论知识,同时也接受了更加系统和广泛的相关课程和实践,比如算法、计算机网络、操作系统、软件工程等等。他们研究

    2024年02月06日
    浏览(58)
  • 【程序员将面临失业吗?】——全球首位AI程序员诞生,将会对程序员的影响有多大?

    全球首位AI程序员的诞生将推动编程领域向着更加智能化、自动化的方向发展,程序员将面临新的机遇和挑战,需要不断适应和学习,才能保持竞争力。   方向一:AI程序员的优势分析 高效的自动化工具使用能力: AI程序员熟练掌握各种AI技术和工具,能够利用自动化工具快

    2024年04月09日
    浏览(98)
  • 程序员能干多久?程序员能干到多大年龄?

    程序员可以工作多少年?大多数程序员认为程序员是吃青春饭的工作。编程只能干到30岁,最长可达35岁。我经常听到这样的话,都让人倍感压力。今天,我们来谈谈这个老话题...... 程序员能干多久? 根据国外的经验来说,干到退休没问题! 国内由于起步晚,公司制度规范不健

    2023年04月23日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包