为项目添加 null 标记和 final 标记优化

This commit is contained in:
A.C.Sukazyo Eyre 2021-11-27 21:07:40 +08:00
parent 4e89f67496
commit 5e22dc0b8f
Signed by: Eyre_S
GPG Key ID: EFB47D98FE082FAD
14 changed files with 109 additions and 79 deletions

View File

@ -1,12 +1,13 @@
plugins { plugins {
id 'java' id 'java'
id 'java-library'
id 'maven-publish' id 'maven-publish'
id 'application' id 'application'
id 'com.github.johnrengelman.shadow' version '7.1.0' id 'com.github.johnrengelman.shadow' version '7.1.0'
} }
group 'cc.sukazyo' group 'cc.sukazyo'
version '0.3.3' version '0.3.4'
project.ext.archiveBaseName = 'Coeur_Morny_Cono' project.ext.archiveBaseName = 'Coeur_Morny_Cono'
project.ext.artifactId = 'morny-coeur' project.ext.artifactId = 'morny-coeur'
mainClassName = 'cc.sukazyo.cono.morny.MornyCoeur' mainClassName = 'cc.sukazyo.cono.morny.MornyCoeur'
@ -17,6 +18,8 @@ repositories {
dependencies { dependencies {
compileOnlyApi "com.github.spotbugs:spotbugs-annotations:4.5.0"
implementation 'com.github.pengrad:java-telegram-bot-api:5.3.0' implementation 'com.github.pengrad:java-telegram-bot-api:5.3.0'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'

View File

@ -2,30 +2,33 @@ package cc.sukazyo.cono.morny;
import cc.sukazyo.cono.morny.util.StringUtils; import cc.sukazyo.cono.morny.util.StringUtils;
import javax.annotation.Nonnull;
public class Logger { public class Logger {
public static final Logger logger = new Logger(); public static final Logger logger = new Logger();
public void info(String message) { public void info(@Nonnull String message) {
System.out.println(formatMessage(message, "INFO")); System.out.println(formatMessage(message, "INFO"));
} }
public void warn (String message) { public void warn (@Nonnull String message) {
waring(message); waring(message);
} }
public void waring (String message) { public void waring (@Nonnull String message) {
System.out.println(formatMessage(message, "WARN")); System.out.println(formatMessage(message, "WARN"));
} }
public void error (String message) { public void error (@Nonnull String message) {
System.out.println(formatMessage(message, "ERRO")); System.out.println(formatMessage(message, "ERRO"));
} }
private String formatMessage (String message, String level) { @Nonnull
String prompt = String.format("[%s][%s]", System.currentTimeMillis(), Thread.currentThread().getName()); private String formatMessage (@Nonnull String message, @Nonnull String level) {
String levelStr = String.format("[%s]", level); final String prompt = String.format("[%s][%s]", System.currentTimeMillis(), Thread.currentThread().getName());
String newline = "\n" + StringUtils.repeatChar('\'', prompt.length()) + levelStr; final String levelStr = String.format("[%s]", level);
final String newline = "\n" + StringUtils.repeatChar('\'', prompt.length()) + levelStr;
return prompt + levelStr + message.replaceAll("\\n", newline); return prompt + levelStr + message.replaceAll("\\n", newline);
} }

View File

@ -6,6 +6,8 @@ import cc.sukazyo.cono.morny.data.tracker.TrackerDataManager;
import com.pengrad.telegrambot.TelegramBot; import com.pengrad.telegrambot.TelegramBot;
import com.pengrad.telegrambot.request.GetMe; import com.pengrad.telegrambot.request.GetMe;
import javax.annotation.Nonnull;
import static cc.sukazyo.cono.morny.Logger.logger; import static cc.sukazyo.cono.morny.Logger.logger;
public class MornyCoeur { public class MornyCoeur {
@ -13,7 +15,7 @@ public class MornyCoeur {
private static TelegramBot account; private static TelegramBot account;
public static final String USERNAME = "morny_cono_annie_bot"; public static final String USERNAME = "morny_cono_annie_bot";
public static void main (String[] args) { public static void main (@Nonnull String[] args) {
if (!(args.length > 1 && "--no-hello".equals(args[1]))) if (!(args.length > 1 && "--no-hello".equals(args[1])))
logger.info(MornyHello.MORNY_PREVIEW_IMAGE_ASCII); logger.info(MornyHello.MORNY_PREVIEW_IMAGE_ASCII);
@ -47,13 +49,14 @@ public class MornyCoeur {
Runtime.getRuntime().addShutdownHook(new Thread(MornyCoeur::exitCleanup)); Runtime.getRuntime().addShutdownHook(new Thread(MornyCoeur::exitCleanup));
} }
public static TelegramBot login (String key) { @Nonnull
TelegramBot account = new TelegramBot(key); public static TelegramBot login (@Nonnull String key) {
final TelegramBot account = new TelegramBot(key);
logger.info("Trying to login..."); logger.info("Trying to login...");
for (int i = 1; i < 4; i++) { for (int i = 1; i < 4; i++) {
if (i != 1) logger.info("retrying..."); if (i != 1) logger.info("retrying...");
try { try {
String username = account.execute(new GetMe()).user().username(); final String username = account.execute(new GetMe()).user().username();
if (!USERNAME.equals(username)) if (!USERNAME.equals(username))
throw new RuntimeException("Required the bot @"+USERNAME + " but @"+username + " logged in!"); throw new RuntimeException("Required the bot @"+USERNAME + " but @"+username + " logged in!");
logger.info("Succeed login to @" + username); logger.info("Succeed login to @" + username);

View File

@ -2,12 +2,14 @@ package cc.sukazyo.cono.morny;
import cc.sukazyo.cono.morny.util.FileUtils; import cc.sukazyo.cono.morny.util.FileUtils;
import javax.annotation.Nonnull;
import java.net.URISyntaxException; import java.net.URISyntaxException;
public class MornySystem { public class MornySystem {
public static final String VERSION = "0.3.3"; public static final String VERSION = "0.3.4";
@Nonnull
public static String getJarMd5() { public static String getJarMd5() {
try { try {
return FileUtils.getMD5Three(MornyCoeur.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); return FileUtils.getMD5Three(MornyCoeur.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());

View File

@ -8,7 +8,7 @@ public class MornyTrusted {
public static final long TRUSTED_CHAT_ID = -1001541451710L; public static final long TRUSTED_CHAT_ID = -1001541451710L;
public static boolean isTrusted (long userId) { public static boolean isTrusted (long userId) {
ChatMember chatMember = MornyCoeur.getAccount().execute(new GetChatMember(TRUSTED_CHAT_ID, userId)).chatMember(); final ChatMember chatMember = MornyCoeur.getAccount().execute(new GetChatMember(TRUSTED_CHAT_ID, userId)).chatMember();
return ( return (
chatMember != null && ( chatMember != null && (
chatMember.status() == ChatMember.Status.administrator || chatMember.status() == ChatMember.Status.administrator ||

View File

@ -2,58 +2,60 @@ package cc.sukazyo.cono.morny.bot.api;
import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.Update;
import javax.annotation.Nonnull;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public abstract class EventListener { public abstract class EventListener {
public boolean onMessage (Update update) { public boolean onMessage (@Nonnull Update update) {
return false; return false;
} }
public boolean onEditedMessage (Update update) { public boolean onEditedMessage (@Nonnull Update update) {
return false; return false;
} }
public boolean onChannelPost (Update update) { public boolean onChannelPost (@Nonnull Update update) {
return false; return false;
} }
public boolean onEditedChannelPost (Update update) { public boolean onEditedChannelPost (@Nonnull Update update) {
return false; return false;
} }
public boolean onInlineQuery (Update update) { public boolean onInlineQuery (@Nonnull Update update) {
return false; return false;
} }
public boolean onChosenInlineResult (Update update) { public boolean onChosenInlineResult (@Nonnull Update update) {
return false; return false;
} }
public boolean onCallbackQuery (Update update) { public boolean onCallbackQuery (@Nonnull Update update) {
return false; return false;
} }
public boolean onShippingQuery (Update update) { public boolean onShippingQuery (@Nonnull Update update) {
return false; return false;
} }
public boolean onPreCheckoutQuery (Update update) { public boolean onPreCheckoutQuery (@Nonnull Update update) {
return false; return false;
} }
public boolean onPoll (Update update) { public boolean onPoll (@Nonnull Update update) {
return false; return false;
} }
public boolean onPollAnswer (Update update) { public boolean onPollAnswer (@Nonnull Update update) {
return false; return false;
} }
public boolean onMyChatMemberUpdated (Update update) { public boolean onMyChatMemberUpdated (@Nonnull Update update) {
return false; return false;
} }
public boolean onChatMemberUpdated (Update update) { public boolean onChatMemberUpdated (@Nonnull Update update) {
return false; return false;
} }

View File

@ -2,6 +2,7 @@ package cc.sukazyo.cono.morny.bot.api;
import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.Update;
import javax.annotation.Nonnull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -17,7 +18,7 @@ public class EventListenerManager {
private final Function<EventListener, Boolean> exec; private final Function<EventListener, Boolean> exec;
public EventPublisher(Update update, Function<EventListener, Boolean> exec) { public EventPublisher(@Nonnull Update update, @Nonnull Function<EventListener, Boolean> exec) {
this.setName("EVT"+update.updateId()); this.setName("EVT"+update.updateId());
this.exec = exec; this.exec = exec;
} }
@ -36,59 +37,59 @@ public class EventListenerManager {
} }
public static void addListener (EventListener... listeners) { public static void addListener (@Nonnull EventListener... listeners) {
EventListenerManager.listeners.addAll(Arrays.asList(listeners)); EventListenerManager.listeners.addAll(Arrays.asList(listeners));
} }
public static void publishMessageEvent (Update update) { public static void publishMessageEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onMessage(update)).start(); new EventPublisher(update, x -> x.onMessage(update)).start();
} }
public static void publishEditedMessageEvent (Update update) { public static void publishEditedMessageEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onEditedMessage(update)).start(); new EventPublisher(update, x -> x.onEditedMessage(update)).start();
} }
public static void publishChannelPostEvent (Update update) { public static void publishChannelPostEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onChannelPost(update)).start(); new EventPublisher(update, x -> x.onChannelPost(update)).start();
} }
public static void publishEditedChannelPostEvent (Update update) { public static void publishEditedChannelPostEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onEditedChannelPost(update)).start(); new EventPublisher(update, x -> x.onEditedChannelPost(update)).start();
} }
public static void publishInlineQueryEvent (Update update) { public static void publishInlineQueryEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onInlineQuery(update)).start(); new EventPublisher(update, x -> x.onInlineQuery(update)).start();
} }
public static void publishChosenInlineResultEvent (Update update) { public static void publishChosenInlineResultEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onChosenInlineResult(update)).start(); new EventPublisher(update, x -> x.onChosenInlineResult(update)).start();
} }
public static void publishCallbackQueryEvent (Update update) { public static void publishCallbackQueryEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onCallbackQuery(update)).start(); new EventPublisher(update, x -> x.onCallbackQuery(update)).start();
} }
public static void publishShippingQueryEvent (Update update) { public static void publishShippingQueryEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onShippingQuery(update)).start(); new EventPublisher(update, x -> x.onShippingQuery(update)).start();
} }
public static void publishPreCheckoutQueryEvent (Update update) { public static void publishPreCheckoutQueryEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onPreCheckoutQuery(update)).start(); new EventPublisher(update, x -> x.onPreCheckoutQuery(update)).start();
} }
public static void publishPollEvent (Update update) { public static void publishPollEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onPoll(update)).start(); new EventPublisher(update, x -> x.onPoll(update)).start();
} }
public static void publishPollAnswerEvent (Update update) { public static void publishPollAnswerEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onPollAnswer(update)).start(); new EventPublisher(update, x -> x.onPollAnswer(update)).start();
} }
public static void publishMyChatMemberUpdatedEvent (Update update) { public static void publishMyChatMemberUpdatedEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onMyChatMemberUpdated(update)).start(); new EventPublisher(update, x -> x.onMyChatMemberUpdated(update)).start();
} }
public static void publishChatMemberUpdatedEvent (Update update) { public static void publishChatMemberUpdatedEvent (@Nonnull Update update) {
new EventPublisher(update, x -> x.onChatMemberUpdated(update)).start(); new EventPublisher(update, x -> x.onChatMemberUpdated(update)).start();
} }

View File

@ -3,11 +3,12 @@ package cc.sukazyo.cono.morny.bot.api;
import com.pengrad.telegrambot.UpdatesListener; import com.pengrad.telegrambot.UpdatesListener;
import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.Update;
import javax.annotation.Nonnull;
import java.util.List; import java.util.List;
public class OnUpdate { public class OnUpdate {
public static int onNormalUpdate (List<Update> updates) { public static int onNormalUpdate (@Nonnull List<Update> updates) {
for (Update update : updates) { for (Update update : updates) {
if (update.message() != null) { if (update.message() != null) {
EventListenerManager.publishMessageEvent(update); EventListenerManager.publishMessageEvent(update);

View File

@ -5,10 +5,12 @@ import cc.sukazyo.cono.morny.data.tracker.TrackerDataManager;
import com.pengrad.telegrambot.model.Chat; import com.pengrad.telegrambot.model.Chat;
import com.pengrad.telegrambot.model.Update; import com.pengrad.telegrambot.model.Update;
import javax.annotation.Nonnull;
public class OnActivityRecord extends EventListener { public class OnActivityRecord extends EventListener {
@Override @Override
public boolean onMessage (Update update) { public boolean onMessage (@Nonnull Update update) {
if ( if (
update.message().chat().type() == Chat.Type.supergroup || update.message().chat().type() == Chat.Type.supergroup ||
update.message().chat().type() == Chat.Type.group update.message().chat().type() == Chat.Type.group

View File

@ -11,6 +11,8 @@ import com.pengrad.telegrambot.model.request.ParseMode;
import com.pengrad.telegrambot.request.SendMessage; import com.pengrad.telegrambot.request.SendMessage;
import com.pengrad.telegrambot.request.SendSticker; import com.pengrad.telegrambot.request.SendSticker;
import javax.annotation.Nonnull;
import static cc.sukazyo.cono.morny.Logger.logger; import static cc.sukazyo.cono.morny.Logger.logger;
public class OnCommandExecute extends EventListener { public class OnCommandExecute extends EventListener {
@ -21,11 +23,11 @@ public class OnCommandExecute extends EventListener {
private static final String EXIT_403_STICKER_ID = "CAACAgEAAxkBAAMqYYYa_7hpXH6hMOYMX4Nh8AVYd74AAnQnAAJ4_MYFRdmmsQKLDZgiBA"; private static final String EXIT_403_STICKER_ID = "CAACAgEAAxkBAAMqYYYa_7hpXH6hMOYMX4Nh8AVYd74AAnQnAAJ4_MYFRdmmsQKLDZgiBA";
@Override @Override
public boolean onMessage (Update event) { public boolean onMessage (@Nonnull Update event) {
if (event.message().text() == null) { if (event.message().text() == null) {
return false; return false;
} }
String[] command = StringUtils.formatCommand(event.message().text()); final String[] command = StringUtils.formatCommand(event.message().text());
if (command.length == 0) return false; if (command.length == 0) return false;
switch (command[0]) { switch (command[0]) {
case "/user": case "/user":
@ -56,7 +58,7 @@ public class OnCommandExecute extends EventListener {
return true; return true;
} }
private void onCommandOnExec (Update event) { private void onCommandOnExec (@Nonnull Update event) {
MornyCoeur.getAccount().execute(new SendSticker( MornyCoeur.getAccount().execute(new SendSticker(
event.message().chat().id(), event.message().chat().id(),
ONLINE_STATUS_RETURN_STICKER_ID ONLINE_STATUS_RETURN_STICKER_ID
@ -64,7 +66,7 @@ public class OnCommandExecute extends EventListener {
); );
} }
private void onCommandHelloExec (Update event) { private void onCommandHelloExec (@Nonnull Update event) {
MornyCoeur.getAccount().execute(new SendSticker( MornyCoeur.getAccount().execute(new SendSticker(
event.message().chat().id(), event.message().chat().id(),
HELLO_STICKER_ID HELLO_STICKER_ID
@ -72,7 +74,7 @@ public class OnCommandExecute extends EventListener {
); );
} }
private void onCommandExitExec (Update event) { private void onCommandExitExec (@Nonnull Update event) {
if (MornyTrusted.isTrusted(event.message().from().id())) { if (MornyTrusted.isTrusted(event.message().from().id())) {
MornyCoeur.getAccount().execute(new SendSticker( MornyCoeur.getAccount().execute(new SendSticker(
event.message().chat().id(), event.message().chat().id(),
@ -91,7 +93,7 @@ public class OnCommandExecute extends EventListener {
} }
} }
private void onCommandVersionExec (Update event) { private void onCommandVersionExec (@Nonnull Update event) {
MornyCoeur.getAccount().execute(new SendMessage( MornyCoeur.getAccount().execute(new SendMessage(
event.message().chat().id(), event.message().chat().id(),
String.format( String.format(

View File

@ -8,11 +8,13 @@ import com.pengrad.telegrambot.model.User;
import com.pengrad.telegrambot.model.request.ParseMode; import com.pengrad.telegrambot.model.request.ParseMode;
import com.pengrad.telegrambot.request.SendMessage; import com.pengrad.telegrambot.request.SendMessage;
import javax.annotation.Nonnull;
public class OnUserSlashAction extends EventListener { public class OnUserSlashAction extends EventListener {
@Override @Override
public boolean onMessage (Update event) { public boolean onMessage (@Nonnull Update event) {
String text = event.message().text(); final String text = event.message().text();
if (text == null) return false; if (text == null) return false;
if (text.startsWith("/")) { if (text.startsWith("/")) {
@ -31,12 +33,12 @@ public class OnUserSlashAction extends EventListener {
prefixLength = 2; prefixLength = 2;
} }
String[] action = StringUtils.formatCommand(text.substring(prefixLength)); final String[] action = StringUtils.formatCommand(text.substring(prefixLength));
String verb = action[0]; final String verb = action[0];
boolean hasObject = action.length != 1; final boolean hasObject = action.length != 1;
String object = StringUtils.connectStringArray(action, " ", 1, action.length-1); final String object = StringUtils.connectStringArray(action, " ", 1, action.length-1);
User origin = event.message().from(); final User origin = event.message().from();
User target = (event.message().replyToMessage() == null ? ( final User target = (event.message().replyToMessage() == null ? (
origin origin
): ( ): (
event.message().replyToMessage().from() event.message().replyToMessage().from()

View File

@ -8,9 +8,11 @@ import com.pengrad.telegrambot.request.GetChatMember;
import com.pengrad.telegrambot.request.SendMessage; import com.pengrad.telegrambot.request.SendMessage;
import com.pengrad.telegrambot.response.GetChatMemberResponse; import com.pengrad.telegrambot.response.GetChatMemberResponse;
import javax.annotation.Nonnull;
public class GetUsernameAndId { public class GetUsernameAndId {
public static void exec (String[] command, Update event) { public static void exec (@Nonnull String[] command, @Nonnull Update event) {
if (command.length > 2) { MornyCoeur.getAccount().execute(new SendMessage( if (command.length > 2) { MornyCoeur.getAccount().execute(new SendMessage(
event.message().chat().id(), event.message().chat().id(),
@ -42,7 +44,7 @@ public class GetUsernameAndId {
return; return;
} }
GetChatMemberResponse response = MornyCoeur.getAccount().execute( final GetChatMemberResponse response = MornyCoeur.getAccount().execute(
new GetChatMember(event.message().chat().id(), userId) new GetChatMember(event.message().chat().id(), userId)
); );
@ -54,9 +56,9 @@ public class GetUsernameAndId {
return; return;
} }
User user = response.chatMember().user(); final User user = response.chatMember().user();
StringBuilder userInformation = new StringBuilder(); final StringBuilder userInformation = new StringBuilder();
userInformation.append(String.format( userInformation.append(String.format(
"userid :\n" + "userid :\n" +
"- <code>%d</code>\n" + "- <code>%d</code>\n" +

View File

@ -1,6 +1,6 @@
package cc.sukazyo.cono.morny.util; package cc.sukazyo.cono.morny.util;
import java.io.File; import javax.annotation.Nonnull;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
@ -9,19 +9,19 @@ import java.security.NoSuchAlgorithmException;
public class FileUtils { public class FileUtils {
public static String getMD5Three (String path) { @Nonnull
BigInteger bi; public static String getMD5Three (@Nonnull String path) {
final BigInteger bi;
try { try {
byte[] buffer = new byte[8192]; final byte[] buffer = new byte[8192];
int len; int len;
MessageDigest md = MessageDigest.getInstance("MD5"); final MessageDigest md = MessageDigest.getInstance("MD5");
File f = new File(path); final FileInputStream fis = new FileInputStream(path);
FileInputStream fis = new FileInputStream(f);
while ((len = fis.read(buffer)) != -1) { while ((len = fis.read(buffer)) != -1) {
md.update(buffer, 0, len); md.update(buffer, 0, len);
} }
fis.close(); fis.close();
byte[] b = md.digest(); final byte[] b = md.digest();
bi = new BigInteger(1, b); bi = new BigInteger(1, b);
} catch (NoSuchAlgorithmException | IOException e) { } catch (NoSuchAlgorithmException | IOException e) {
e.printStackTrace(System.out); e.printStackTrace(System.out);

View File

@ -1,22 +1,26 @@
package cc.sukazyo.cono.morny.util; package cc.sukazyo.cono.morny.util;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
public class StringUtils { public class StringUtils {
@Nonnull
public static String repeatChar (char c, int i) { public static String repeatChar (char c, int i) {
char[] chars = new char[i]; final char[] chars = new char[i];
Arrays.fill(chars, c); Arrays.fill(chars, c);
return new String(chars); return new String(chars);
} }
public static String[] formatCommand (String com) { @Nonnull
public static String[] formatCommand (@Nonnull String com) {
ArrayList<String> arr = new ArrayList<>(); final ArrayList<String> arr = new ArrayList<>();
StringBuilder tmp = new StringBuilder(); final StringBuilder tmp = new StringBuilder();
char[] coma = com.toCharArray(); final char[] coma = com.toCharArray();
for (int i = 0; i < coma.length; i++) { for (int i = 0; i < coma.length; i++) {
if (coma[i] == ' ') { if (coma[i] == ' ') {
if (!tmp.toString().equals("")) { arr.add(tmp.toString()); } if (!tmp.toString().equals("")) { arr.add(tmp.toString()); }
@ -43,14 +47,17 @@ public class StringUtils {
if (!tmp.toString().equals("")) { arr.add(tmp.toString()); } if (!tmp.toString().equals("")) { arr.add(tmp.toString()); }
tmp.setLength(0); tmp.setLength(0);
String[] out = new String[arr.size()]; final String[] out = new String[arr.size()];
arr.toArray(out); arr.toArray(out);
return out; return out;
} }
public static String connectStringArray (String[] array, String connector, int startIndex, int stopIndex) { @Nonnull
StringBuilder builder = new StringBuilder(); public static String connectStringArray (
@Nonnull String[] array, @Nonnull String connector, @Nonnegative int startIndex, @Nonnegative int stopIndex
) {
final StringBuilder builder = new StringBuilder();
for (int i = startIndex; i < stopIndex; i++) { for (int i = startIndex; i < stopIndex; i++) {
builder.append(array[i]); builder.append(array[i]);
builder.append(connector); builder.append(connector);