如何写好Java程序呢

2023-11-16

如何写出更好的Java代码

  • 05/22. 2014

Java是最流行的编程语言之一,但似乎并没有人喜欢使用它。好吧,实际上Java是一门还不错的编程语言,由于最近Java 8发布了,我决定来编辑一个如何能更好地使用Java的列表,这里面包括一些库,实践技巧以及工具。

这篇文章在GitHub上也有。你可以随时在上面贡献或者添加你自己的Java使用技巧或者最佳实践。

  • 编码风格
    • 结构体
      • builder模式
    • 依赖注入
    • 避免null值
    • 不可变
    • 避免过多的工具类
    • 格式
      • 文档
      • Stream
  • 部署
    • 框架
    • Maven
      • 依赖收敛
    • 持续集成
    • Maven仓储
    • 配置管理
    • 遗失的特性
      • Apache Commons
      • Guava
      • Gson
      • Java Tuples
      • Joda-Time
      • Lombok
      • Play framework
      • SLF4J
      • jOOQ
    • 测试
      • jUnit 4
      • jMock
      • AssertJ
  • 工具
    • IntelliJ IDEA
      • Chronon
    • JRebel
    • 校验框架
    • Eclipse Memory Analyzer
  • 资源
    • 书籍
    • 播客

编码风格

传统的Java编码方式是非常啰嗦的企业级JavaBean的风格。新的风格更简洁准确,对眼睛也更好。

结构体

我们这些码农干的最简单的事情就是传递数据了。传统的方式就是定义一个JavaBean:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DataHolder {
     private String data ;
 
     public DataHolder ( ) {
     }
 
     public void setData ( String data ) {
         this . data = data ;
     }
 
     public String getData ( ) {
         return this . data ;
     }
}

这不仅拖沓而且浪费。尽管你的IDE可以自动地生成这个,但这还是浪费。因此,不要这么写

相反的,我更喜欢C的结构体的风格,写出来的类只是包装数据:

1
2
3
4
5
6
7
public class DataHolder {
     public final String data ;
 
     public DataHolder ( String data ) {
         this . data = data ;
     }
}

这样写减少了一半的代码。不仅如此,除非你继承它,不然这个类是不可变的,由于它是不可变的,因此推断它的值就简单多了。

如果你存储的是Map或者List这些可以容易被修改的数据,你可以使用ImmutableMap或者ImmutableList,这个在不可变性这节中会有讨论。

Builder模式

如果你有一个相对复杂的对象,可以考虑下Builder模式。

你在对象里边创建一个子类,用来构造你的这个对象。它使用的是可修改的状态,但一旦你调用了build方法,它会生成一个不可变对象。

想象一下我们有一个非常复杂的对象DataHolder。它的构造器看起来应该是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class ComplicatedDataHolder {
     public final String data ;
     public final int num ;
     // lots more fields and a constructor
 
     public class Builder {
         private String data ;
         private int num ;
 
         public Builder data ( String data ) {
             this . data = data ;
             return this ;
         }
 
         public Builder num ( int num ) {
             this . num = num ;
             return this ;
         }
 
         public ComplicatedDataHolder build ( ) {
             return new ComplicatedDataHolder ( data , num ) ; // etc
         }
     }
}
 

现在你可以使用它了:

1
2
3
4
final ComplicatedDataHolder cdh = new ComplicatedDataHolder . Builder ( )
     . data ( "set this" )
     . num ( 523 )
     . build ( ) ;

关于Builder的使用这里还有些更好的例子,我这里举的例子只是想让你大概感受一下。当然这会产生许多我们希望避免的样板代码,不过好处就是你有了一个不可变对象以及一个连贯接口。

依赖注入

这更像是一个软件工程的章节而不是Java的,写出可测的软件的一个最佳方式就是使用依赖注入(Dependency injection,DI)。由于Java强烈鼓励使用面向对象设计 ,因此想写出可测性强的软件,你需要使用DI。

在Java中,这个通常都是用Spring框架来完成的。它有一个基于XML配置的绑定方式,并且仍然相当流行。重要的一点是你不要因为它的基于XML的配置格式而过度使用它了。在XML中应该没有任何的逻辑和控制结构。它只应该是依赖注入。

还有一个不错的方式是使用Dagger库以及Google的Guice。它们并没有使用Spring的XML配置文件的格式,而是将注入的逻辑放到了注解和代码里。

避免null值

如果有可能的话尽量避免使用null值。你可以返回一个空的集合,但不要返回null集合。如果你准备使用null的话,考虑一下@Nullable注解。IntelliJ IDEA对于@Nullable注解有内建的支持。

如果你使用的是Java 8的话,可以考虑下新的Optional类型。如果一个值可能存在也可能不存在,把它封装到Optional类里面,就像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class FooWidget {
     private final String data ;
     private final Optional & lt ; Bar & gt ; bar ;
 
     public FooWidget ( String data ) {
         this ( data , Optional . empty ( ) ) ;
     }
 
     public FooWidget ( String data , Optional & lt ; Bar & gt ; bar ) {
         this . data = data ;
         this . bar = bar ;
     }
 
     public Optional & lt ; Bar & gt ; getBar ( ) {
         return bar ;
     }
}

现在问题就清楚了,data是不会为null的,而bar可能为空。Optional类有一些像isPresent这样的方法,这让它感觉跟检查null没什么区别。不过有了它你可以写出这样的语句:

1
2
3
4
5
6
final Optional & lt ; FooWidget & gt ; fooWidget = maybeGetFooWidget ( ) ;
final Baz baz = fooWidget . flatMap ( FooWidget :: getBar )
                         . flatMap ( BarWidget :: getBaz )
                         . orElse ( defaultBaz ) ;
 
 

这比使用if来检查null好多了。唯一的缺点就是标准类库中对Optional的支持并不是很好,因此你还是需要对null进行检查的。

不可变

变量,类,集合,这些都应该是不可变的,除非你有更好的理由它们的确需要进行修改。

变量可以通过final来设置成不可变的:

1
2
3
4
5
6
7
8
9
10
11
12
13
final FooWidget fooWidget ;
if ( condition ( ) ) {
     fooWidget = getWidget ( ) ;
} else {
     try {
         fooWidget = cachedFooWidget . get ( ) ;
     } catch ( CachingException e ) {
         log . error ( "Couldn't get cached value" , e ) ;
         throw e ;
     }
}
// fooWidget is guaranteed to be set here

现在你可以确认fooWidget不会不小心被重新赋值了。final关键字可以和if/else块以及try/catch块配合使用。当然了,如果fooWidget对象不是不可变的,你也可以很容易地对它进行修改。

有可能的话,集合都应该尽量使用Guava的ImmutableMap, ImmutableList, or ImmutableSet类。这些类都有自己的构造器,你可以动态的创建它们,然后将它们设置成不可变的,。

要使一个类不可变,你可以将它的字段声明成不可变的(设置成final)。你也可以把类自身也设置成final的这样它就不能被扩展并且修改了,当然这是可选的。

避免大量的工具类

如果你发现自己添加了许多方法到一个Util类里,你要注意了。

1
2
3
4
5
6
7
8
9
10
public class MiscUtil {
     public static String frobnicateString ( String base , int times ) {
         // ... etc
     }
 
     public static void throwIfCondition ( boolean condition , String msg ) {
         // ... etc
     }
}

这些类乍一看挺吸引人的,因为它们里面的这些方法不属于任何一个地方。因此你以代码重用之名将它们全都扔到这里了。

这么解决问题结果更糟。把它们放回它们原本属于的地方吧,如果你确实有一些类似的常用方法,考虑下Java 8里接口的默认方法。并且由于它们是接口,你可以实现多个方法。

1
2
3
4
5
6
7
8
9
10
public interface Thrower {
     public void throwIfCondition ( boolean condition , String msg ) {
         // ...
     }
 
     public void throwAorB ( Throwable a , Throwable b , boolean throwA ) {
         // ...
     }
}

这样需要使用它的类只需简单的实现下这个接口就可以了。

格式

格式远比许多程序员相像的要重要的多。一致的格式说明你关注自己的代码或者对别人有所帮助?是的。不过你先不要着急为了让代码整齐点而浪费一整天的时间在那给if块加空格了。

如果你确实需要一份代码格式规范,我强烈推荐Google的Java风格指南。这份指南最精彩的部分就是编程实践这节了。非常值得一读。

文档

面向用户的代码编写下文档还是很重要的。这意味着你需要提供一些使用的示例,同时你的变量方法和类名都应该有适当的描述信息。

结论就是不要给不需要文档的地方添加文档。如果对于某个参数你没什么可说的,或者它已经非常明显了,别写文档了。模板化的文档比没有文档更糟糕,因为它欺骗了你的用户,让他觉得这里有文档。

Java 8有一个漂亮的流和lambda表达式的语法。你的代码可以这么写:

1
2
3
4
5
final List & lt ; String & gt ; filtered = list . stream ( )
     . filter ( s - & gt ; s . startsWith ( "s" ) )
     . map ( s - & gt ; s . toUpperCase ( ) ) ;
 
 

而不是这样:

1
2
3
4
5
6
7
final List & lt ; String & gt ; filtered = Lists . newArrayList ( ) ;
for ( String str : list ) {
     if ( str . startsWith ( "s" ) {
         filtered . add ( str . toUpperCase ( ) ) ;
     }
}

这样你能写出更连贯的代码,可读性也更强。

部署

正确地部署Java程序还是需要点技巧的。现在部署Java代码的主流方式有两种 :使用框架或者使用自家摸索出来的解决方案,当然那样更灵活。

框架

由于部署Java程序并不容易,因此才有了各种框架来用于部署。最好的两个是Dropwizard以及Spring BootPlay Framework也可以算是一个部署框架。

这些框架都试图降低部署程序的门槛。如果你是一个Java的新手或者你需要快速把事情搞定的话,那么框架就派上用场了。单个jar的部署当然会比复杂的WAR或者EAR部署要更容易一些。

然而,这些框架的灵活性不够,并且相当顽固,因此如果这些框架的开发人员给出的方式不太适合你的项目的话,你只能自己进行配置了。

Maven

备选方案:Gradle

Maven仍然是编译,打包,运行测试的标准化工具。还有其它一些选择,比如Gradle,不过它们的采用程度远不Maven。如果你之前没用过Maven,你可以看下这个Maven的使用示例

我喜欢用一个根POM文件来包含所有的外部依赖。它看起来就像是这样。这个根POM文件只有一个外部依赖,不过如果你的产品很大的话,你可能会有很多依赖。你的根POM文件自己就应该是一个项目:它有版本控制,并且和其它的Java项目一样进行发布。

如果你觉得为每个外部依赖的修改都给POM文件打个标签(tag)有点太浪费了,那是你还没有经历过花了一个星期的时间来跟踪项目依赖错误的问题。

你的所有Maven工程都应该包含你的主POM文件以及所有的版本信息。这样的话,你能知道公司项目的每个外部依赖所选择的版本,以及所有正确的Maven插件。如果你需要引入一个外部依赖的话,大概是这样的:

1
2
3
4
5
6
7
8
& lt ; dependencies & gt ;
     & lt ; dependency & gt ;
         & lt ; groupId & gt ; org . third . party & lt ; / groupId & gt ;
         & lt ; artifactId & gt ; some - artifact & lt ; / artifactId & gt ;
     & lt ; / dependency & gt ;
& lt ; / dependencies & gt ;
 
 

如果你需要进行内部依赖的话,应该在项目的段中单独进行维护。不然的话,主POM文件的版本号就要疯涨了。

依赖收敛

Java的一个最好的地方就是有大量的第三方库,它们无所不能。几乎每个API或者工具都有相应的Java SDK,并且可以很容易地引入到Maven中来。

所有的这些Java库自身可能又会依赖一些特定的版本的其它类库。如果你引入了大量的库,可能会出现版本冲突 ,比如说像这样:

1
2
3
4
Foo library depends on Bar library v1 . 0
Widget library depends on Bar library v0 . 9
 
 

你的工程应该引入哪个版本?

有了Maven的依赖收敛的插件后,如果你的依赖版本不一致的话,编译的时候就会报错。那么你有两种解决冲突的方案:

  • 在dependencyManagement区中显式地选择某个版本的bar。
  • Foo或者Widget都不要依赖Bar。

到底选择哪种方案取决你的具体情况: 如果你想要跟踪某个工程的版本,不依赖它是最好的。另一方面,如果你想要明确一点,你可以自己选择一个版本,不过这样的话,如果更新了其它的依赖,也得同步地修改它。

持续集成

很明显你需要某种持续集成的服务器来不断地编译你的SNAPSHOT版本,或者对Git分支进行构建。

JenkinsTravis-CI是你的不二选择。

代码覆盖率也很重要,Cobertura有一个不错的Maven插件,并且对CI支持的也不错。当然还有其它的代码覆盖的工具,不过我用的是Cobertura。

Maven库

你需要一个地方来存储你编译好的jar包,war包,以及EAR包,因此你需要一个代码仓库。

常见的选择是Artifactory或者Nexus。两个都能用,并且各有利弊。

你应该自己进行Artifactory/Nexus的安装并且将你的依赖做一份镜像。这样不会由于下载Maven 库的时候出错了导到编译中断。

配置管理

那现在你的代码可以编译了,仓库也搭建起来了,你需要把你的代码带出开发环境,走向最终的发布了。别马虎了,因为自动化执行从长远来看,好处是大大的。

ChefPuppet,和Ansible都是常见的选择。我自己也写了一个可选方案,Squadron。这个嘛,当然了,我自然是希望你们能下载下它的,因为它比其它那些要好用多了。

不管你用的是哪个工具,别忘了自动化部署就好。

可能Java最好的特性就是它拥有的这些库了。下面列出了一些库,应该绝大多数人都会用得上。

Java的标准库,曾经还是很不错的,但在现在看来它也遗漏掉了很多关键的特性。

Apache Commons

Apache Commons项目有许多有用的功能。

  • Commons Codec有许多有用的Base64或者16进制字符串的编解码的方法。别浪费时间自己又写一遍了。
  • Commons Lang是一个字符串操作,创建,字符集,以及许多工具方法的类库。
  • Commons IO,你想要的文件相关的方法都在这里了。它有FileUtils.copyDirectory,FileUtils.writeStringToFile, IOUtils.readLines,等等。
Guava

Guava是一个非常棒的库,它就是Java标准库”所缺失的那部分”。它有很多我喜欢的地方,很难一一赘述,不过我还是想试一下。

  • Cache,这是一个最简单的获取内存缓存的方式了,你可以用它来缓存网络访问,磁盘访问,或者几乎所有东西。你只需实现一个CacheBuilder,告诉Guava如何创建缓存就好了。
  • 不可变集合。这里有许多类:ImmutableMap, ImmutableList,甚至还有ImmutableSortedMultiSet,如果这就是你想要的话。

我还喜欢用Guava的方式来新建可变集合:

1
2
3
4
5
6
7
// Instead of
final Map & lt ; String , Widget & gt ; map = new HashMap & lt ; String , Widget & gt ; ( ) ;
 
// You can use
final Map & lt ; String , Widget & gt ; map = Maps . newHashMap ( ) ;
 
 

有许多像Lists, Maps, Sets的静态类,他们都更简洁易懂一些。

如果你还在坚持使用Java 6或者7的话,你可以用下Collections2,它有一些诸如filter和transform的方法。没有Jvaa 8的stream的支持,你也可以用它们来写出连贯的代码。

Guava也有一些很简单的东西,比如Joiner,你可以用它来拼接字符串,还有一个类可以用来处理中断

Gson

Google的Gson是一个简单高效的JSON解析库。它是这样工作的:

1
2
3
4
5
6
final Gson gson = new Gson ( ) ;
final String json = gson . toJson ( fooWidget ) ;
 
final FooWidget newFooWidget = gson . fromJson ( json , FooWidget . class ) ;
 
 

真的很简单,使用它会感觉非常愉快。Gson的用户指南中有更多的示例。

Java Tuples

我对Java一个不爽的地方就是它的标准库中居然没有元组。幸运的是, Java tuples工程解决了这一问题。

它也很容易使用,并且真的很赞:

1
2
3
4
5
6
Pair & lt ; String , Integer & gt ; func ( String input ) {
     // something...
     return Pair . with ( stringResult , intResult ) ;
}
 
 
Joda-Time

Joda-Time是我用过的最好的时间库了。简直,直接,容易测试。你还想要什么?

这个库里我最喜欢的一个类就是Duration,因为我用它来告诉说我要等待多长时间,或者过多久我才进行重试。

Lombok

Lombok是一个非常有趣的库。它通过注释来减少了Java中的饱受诟病的样板代码(注:setter,getter之类的)。

想给你类中的变量增加setter, getter方法?太简单了:

1
2
3
4
5
public class Foo {
     @ Getter @ Setter private int var ;
}
 
 

现在你可以这么写了:

1
2
3
4
final Foo foo = new Foo ( ) ;
foo . setVar ( 5 ) ;
 
 

这里还有更多的示例。我还没在生产代码中用过Lombok,不过我有点等不及了。

Play框架

备选方案:Jersey或者Spark

在Java中实现REST风格的WEB服务有两大阵营:JAX-RS和其它。

JAX-RS是传统的方式。你使用像Jersey这样的东西来将注解和接口,实现组合到一起来实现WEB服务。这样做的好处就是,你可以通过一个接口就能很容易创建出一个调用的客户端来。

Play框架是在JVM上实现WEB服务的截然不同的一种方式:你有一个routes文件,然后你去实现routes中那些规则所引用到的类。它其实就是个完整的MVC框架,不过你可以只用它来实现REST服务。

它同时支持Java和Scala。它优先使用Scala这点可能有点令人沮丧,但是用Java进行开发的话也非常不错。

如果你习惯了Python里的Flask这类的微框架,那么你应该会对Spark感到很熟悉。有了Java 8它简直如虎添翼。

SLF4J

Java打印日志有许多不错的解决方案。我个人最喜欢的是SLF4J,因为它是可挺插拔的,并且可以同时混合不同的日志框架中输出的日志。有个奇怪的工程同时使用了java.util.logging, JCL, 和log4j?没问题,SLF4J就是为它而生的。

想入门的话,看下它的这个两页的手册就足够的了。

jOOQ

我不喜欢很重的ORM框架,因为我喜欢SQL。因此我写了许多的JDBC模板,但它们很难维护。jOOQ是个更不错的解决方案。

你可以在Java中以一种类型安全的方式来书写SQL语句:

1
2
3
4
5
6
7
8
9
10
// Typesafely execute the SQL statement directly with jOOQ
Result & lt ; Record3 & lt ; String , String , String & gt ; & gt ; result =
create . select ( BOOK . TITLE , AUTHOR . FIRST_NAME , AUTHOR . LAST_NAME )
     . from ( BOOK )
     . join ( AUTHOR )
     . on ( BOOK . AUTHOR_ID . equal ( AUTHOR . ID ) )
     . where ( BOOK . PUBLISHED_IN . equal ( 1948 ) )
     . fetch ( ) ;
 
 

将它以及DAO模式结合起来,你可以让数据库访问变得更简单。

测试

测试对软件来说至关重要。下面这些库能让测试变得更加容易。

jUnit 4

jUnit就不用介绍了。它是Java中单元测试的标准工具。

不过可能你还没有完全发挥jUnit的威力。jUnit还支持参数化测试,以及能让你少写很多样板代码的测试规则,还有能随机测试代码的Theory,以及Assumptions

jMock

如果你已经完成了依赖注入,那么它回报你的时候来了:你可以mock出带副作用的代码(就像和REST服务器通信那样),并且仍然能对调用它的代码执行断言操作。

jMock是Java中标准的mock工具。它的使用方式是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class FooWidgetTest {
     private Mockery context = new Mockery ( ) ;
 
     @ Test
     public void basicTest ( ) {
         final FooWidgetDependency dep = context . mock ( FooWidgetDependency . class ) ;
 
         context . checking ( new Expectations ( ) {
             oneOf ( dep ) . call ( with ( any ( String . class ) ) ) ;
             atLeast ( 0 ) . of ( dep ) . optionalCall ( ) ;
         } ) ;
 
         final FooWidget foo = new FooWidget ( dep ) ;
 
         Assert . assertTrue ( foo . doThing ( ) ) ;
         context . assertIsSatisfied ( ) ;
     }
}
 
 

这段代码通过jMock设置了一个FooWidgetDependency ,然后添加了一些期望的操作。我们希望dep的call方法被调用一次而dep的optionalCall 方法会被调用0或更多次。

如果你反复的构造同样的FooWidgetDependency,你应该把它放到一个测试设备(Test Fixture)里,然后把assertIsSatisfied放到一个@After方法中。

AssertJ

你是不是用jUnit写过这些?

1
2
3
4
5
6
7
final List & lt ; String & gt ; result = some . testMethod ( ) ;
assertEquals ( 4 , result . size ( ) ) ;
assertTrue ( result . contains ( "some result" ) ) ;
assertTrue ( result . contains ( "some other result" ) ) ;
assertFalse ( result . contains ( "shouldn't be here" ) ) ;
 
 

这些样板代码有点太聒噪了。AssertJ解决了这个问题。同样的代码可以变成这样:

1
2
3
4
5
assertThat ( some . testMethod ( ) ) . hasSize ( 4 )
                             . contains ( "some result" , "some other result" )
                             . doesNotContain ( "shouldn't be here" ) ;
 
 

连贯接口让你的测试代码可读性更强了。代码如此,夫复何求?

工具

IntelliJ IDEA

备选方案: Eclipse and Netbeans

最好的Java IDE当然是 IntelliJ IDEA。它有许多很棒的特性,我们之所以还能忍受Java这些冗长的代码,它起了很大的作用。自动补全很棒,< a href=”http://i.imgur.com/92ztcCd.png” target=”_blank”>代码检查也超赞,重构工具也非常实用。

免费的社区版对我来说已经足够了,不过在旗舰版中有许多不错的特性比如数据库工具,Srping框架的支持以及Chronon等。

Chronon

GDB 7中我最喜欢的特性就是调试的时候可以按时间进行遍历了。有了IntelliJ IDEA的Chronon插件后,这个也成为现实了。当然你得是旗舰版的。

你可以获取到变量的历史值,跳回前面执行的地方,获取方法的调用历史等等。第一次使用的话会感觉有点怪,但它能帮忙你调试一些很棘手的BUG。

JRebel

持续集成通常都是SaaS产品的一个目标。你想想如果你甚至都不需要等到编译完成就可以看到代码的更新?

这就是JRebel在做的事情。只要你把你的服务器挂到某个JRebel客户端上,代码一旦有改动你马上就能看到效果。当你想快速体验一个功能的话,这个的确能节省不少时间。

验证框架

Java的类型系统是相当弱的。它不能区分出普通字符串以及实际上是正则的字符串,也不能进行

1
2
3
4
5
6
7
8
9
10
< a href = "http://en.wikipedia.org/wiki/Taint_checking" target = "_blank”&gt;污点检查&lt;/a&gt;。而验证框架替它做了。&lt;/p&gt; &lt;p&gt;它使用像@Nullable这样的注解来检查类型,你可以定义自己的注解来让静态代码分析的威力变得更加强大。&lt;/p&gt; &lt;h4&gt;Eclipse Memory Analyzer&lt;/h4&gt; &lt;p&gt;在Java中也会发生内存泄漏。幸运的是,有这类的专门的工具。解决这类问题的最佳工具我觉得就是Eclipse Memory Analyzer了。它能dump出堆的内存,然后帮助你找出泄露的原因:&lt;/p&gt; &lt;p&gt;从JVM进程中dump出堆内存有许多方法,我个人用的是jmap:&lt;/p&gt; &lt;div=" > < code > $ jmap - dump : live , format = b , file = heapdump . hprof - F 8152
Attaching to process ID 8152 , please wait . . .
Debugger attached successfully .
Server compiler detected .
JVM version is 23.25 - b01
Dumping heap to heapdump . hprof . . .
. . . snip . . .
Heap dump file created
 
< / code > < / a >

然后你就可以用Memory Analyzer来打开heapdump.hprof文件,看看到底发生了什么。

资源

好的资源能帮助你成为一名Java大师。

书籍
  • Effective Java
  • Java Concurrency in Practice
播客
1
2
   & lt ; a href = "http://www.javaposse.com/" target = "_blank" & gt ; The Java Posse & lt ; / a & gt ;
 

文章来自:deepinmind

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何写好Java程序呢 的相关文章

  • 在java中轮询Http服务器(重复发送http get请求)

    当对其进行 REST 调用时 我的 Web 服务器会发送一些信息 我想不断轮询该服务器 间隔5秒后重复发送HTTP GET请求 以检查返回的信息是否有任何变化 做到这一点最有效的方法是什么 您能提供一些代码示例吗 请注意 我只想开发客户端代
  • 按下按钮并在java中的新窗口中打开文件

    我创建了一个 JFrame 并放置了一个文本字段和按钮 在文本字段中我放置了从文本文件读取的名称 我知道我想单击按钮并打开一个已知窗口 我想在其中放置名称 其他信息来自同一个文件 这是我的代码 这是我的主框架 package Fronten
  • 两个整数乘积的模

    我必须找到c c a b mod m a b c m 是 32 位整数 但 a b 可以超过 32 位 我正在尝试找出一种计算 c 的方法 而不使用 long 或任何 gt 32 位的数据类型 有任何想法吗 如果m是质数 事情可以简化吗 注
  • 垃圾收集器如何在幕后工作来收集死对象?

    我正在阅读有关垃圾收集的内容 众所周知 垃圾收集会收集死亡对象并回收内存 我的问题是 Collector 如何知道任何对象已死亡 它使用什么数据结构来跟踪活动对象 我正在研究这个问题 我发现GC实际上会跟踪活动对象 并标记它们 每个未标记的
  • 如何在 Java 中向时间戳添加/减去时区偏移量?

    我正在使用 JDK 8 并且玩过ZonedDateTime and Timestamp很多 但我仍然无法解决我面临的问题 假设我得到了格式化的Timestamp在格林威治标准时间 UTC 我的服务器位于某处 假设它设置为Asia Calcu
  • Jframe 内有 2 个 Jdialogs 的 setModal 问题

    当我设置第一个选项时 我遇到了问题JDialog模态 第二个非模态 这是我正在尝试实现的功能 单击 测试对话框 按钮 一个JDialog有名字自定义对话框 主要的将会打开 如果单击 是 选项自定义对话框主 其他JDialog named 自
  • 如何在单个查询中搜索 RealmObject 的 RealmList 字段

    假设我有一堂课 public class Company extends RealmObject private String companyId private RealmList
  • 在 Java 中如何找出哪个对象打开了文件?

    我需要找出答案哪个对象在我的 Java 应用程序中打开了一个文件 这是为了调试 因此欢迎使用工具或实用程序 如果发现哪个对象太具体了 这class也会很有帮助 这可能很棘手 您可以从使用分析器开始 例如VisualVM http visua
  • Java 中如何将 char 转换为 int? [复制]

    这个问题在这里已经有答案了 我是Java编程新手 我有例如 char x 9 我需要得到撇号中的数字 即数字 9 本身 我尝试执行以下操作 char x 9 int y int x 但没有成功 那么我应该怎么做才能得到撇号中的数字呢 ASC
  • 如何在java中将日期格式从YYMMDD更改为YYYY-MM-DD? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我从机器可读代码中获取日期格式为 YYMMDD 如何将其更改为 YYYY MM DD 例如我收到 871223 YYMMDD 我想把它改成
  • Sun 在 EDT 之外做 GUI 工作的演示?

    我正在看SplashDemo java http download oracle com javase tutorial uiswing examples misc SplashDemoProject src misc SplashDemo
  • 如何在字段值无效的情况下更改 Struts2 验证错误消息?

    我在 Web 表单上使用 Struts2 验证 如果字段假设为整数或日期 则
  • 如何在JPanel中设置背景图片

    你好 我使用 JPanel 作为我的框架的容器 然后我真的想在我的面板中使用背景图片 我真的需要帮助 这是我到目前为止的代码 这是更新 请检查这里是我的代码 import java awt import javax swing import
  • hibernate 6.0.2.Final 和 spring boot 2.7.0 的entityManagerFactory bean 未配置问题

    所以最近我想升级我的 Spring Boot 项目项目的一些依赖项 特别是这些组件 雅加达 EE 9 弹簧靴2 7 休眠 6 0 2 Final 完成此操作后 所有更新和代码折射 更新将 javax 导入到 jakarta 以及一些 hib
  • 将 JavaFX FXML 对象分组在一起

    非常具有描述性和信息性的答案将从我这里获得价值 50 声望的赏金 我正在 JavaFX 中开发一个应用程序 对于视图 我使用 FXML
  • Android S8+ 警告消息“不支持当前的显示尺寸设置,可能会出现意外行为”

    我在 Samsung S8 Android 7 中收到此警告消息 APP NAME 不支持当前的显示尺寸设置 可能会 行为出乎意料 它意味着什么以及如何删除它 谢谢 通过添加解决supports screens 机器人 xlargeScre
  • Java 正则表达式中的逻辑 AND

    是否可以在 Java Regex 中实现逻辑 AND 如果答案是肯定的 那么如何实现呢 正则表达式中的逻辑 AND 由一系列堆叠的先行断言组成 例如 foo bar glarch 将匹配包含所有三个 foo bar 和 glarch 的任何
  • Android View Canvas onDraw 未执行

    我目前正在开发一个自定义视图 它在画布上绘制一些图块 这些图块是从多个文件加载的 并将在需要时加载 它们将由 AsyncTask 加载 如果它们已经加载 它们只会被绘制在画布上 这工作正常 如果加载了这些图片 AsyncTask 就会触发v
  • Java/Python 中的快速 IPC/Socket 通信

    我的应用程序中需要两个进程 Java 和 Python 进行通信 我注意到套接字通信占用了 93 的运行时间 为什么通讯这么慢 我应该寻找套接字通信的替代方案还是可以使其更快 更新 我发现了一个简单的修复方法 由于某些未知原因 缓冲输出流似
  • Java RMI - 客户端超时

    我正在使用 Java RMI 构建分布式系统 它必须支持服务器丢失 如果我的客户端使用 RMI 连接到服务器 如果该服务器出现故障 例如电缆问题 我的客户端应该会收到异常 以便它可以连接到其他服务器 但是当服务器出现故障时 我的客户端什么也

随机推荐

  • STM32F1xx IAP跳转App 后中断异常及解决

    网上看到一些网友遇到STM3F1xx系列编写IAP程序经常遇到跳转到App后中断异常的问题 如一触发串口接收中断就复位等 现梳理如下 其实引起上述异常的根本原因就是 共用一组件 中断无入口 如 IAP程序中配置并打开了USART1接收中断
  • 使用Vue实现div上下收缩动画效果

    封装组件
  • springboot原理

    1 什么是SpringBoot SpringBoot是一个快速开发框架 快速的将一些常用的第三方依赖整合 原理 通过Maven子父工程的方式 简化XML配置 全部采用注解形式 内置Http服务器 Jetty和Tomcat 最终以java应用
  • ConstrainLayout解决复杂的嵌套布局

    最近 项目比较忙 没什么时间写博客 今天我要讲的是 项目中复杂的嵌套布局你讲采取何种方式呢 如果按常规方式去做 估计你做完一个界面 估计够呛 我将推荐你们使用谷歌推出的ConstrainLayout 虽然还没有出正式版本 但用于复杂嵌套布局
  • OJ系统刷题 第九篇(难篇)

    13441 求小数的某一位 难题 二刷 三刷 时间限制 1 秒 内存限制 128 MB 分数 tfrac a b ba 化为小数后 小数点后第n位的数字是多少 输入 三个正整数a b n 相邻两个数之间用单个空格隔开 0
  • Windows下好用的终端程序ConEmu

    Windows下的终端程序一直是一个问题 默认的cmd已经老旧不堪 而且在Windows 10中已经取消了在此处打开终端的右键菜单 改为使用功能更加强大的Powershell 而Powershell虽然功能强大 但是默认自带的终端程序却很不
  • COCO数据集解析生成语义分割mask

    COCO数据集解析生成语义分割mask 通过coco数据集的标注文件 instances train2014 json instances val2014 json 生成语义分割mask存在不同类别区域重叠问题 导致重叠部分像素的数值超出
  • linux的PAM认证和shadow文件中密码的加密方式

    它是一种统一的认证方案 PAM 让您能随时改变您的认证方法以及需求 并且不需要重新编译任何代码就封装了所有本地认证方法 具体见 PAM 网站 对于 PAM 您只需要做 对您的密码采用不同于 DES 的加密方式 让它们面对暴力解码 brute
  • “自顶向下,逐步求精“的方法简介

    自顶向下 逐步求精 的方法思路代表了生活中大多数事情的处理方法 它的奥妙之处在于将繁杂棘手的事务进行分解 逐部列条 化为最简易单调的子任务然后进行求解 如图即是一个很典型的逐步分解的问题模型 对于一件既定的事务 先进行总体性的了解即定出整个
  • halcon 中 select_shape 算子 相关特征参数

    求Region指定特征值 region features Regions Features Value 根据特征值选择区域 select shape Regions SelectedRegions Features Operation Mi
  • 安卓初学——界面按钮响应

    安卓学习 采用onClickListener监听器 界面按钮响应 一 定义监听 绑定组件 二 通过匿名内部类 把组件和事件绑定 三 采用view 对象调用onClick 四 在当前Activity实现监听接口 一 定义监听 绑定组件 自定义
  • VMware安装后打开就蓝屏

    VMware虚拟机开机蓝屏 追风 80 人赞同了该文章 目录 收起 一 查看主板上的虚拟化技术支持是否开启 二 开启虚拟机平台 如果在新建的虚拟机安装好后一点开机出现蓝屏 反复重装并且确定了新建虚拟机没有出错的情况下考虑是否是虚拟化没有开启
  • MobaXterm的下载安装

    下载地址 MobaXterm Xserver with SSH telnet RDP VNC and X11 Home Edition 进入页面后 点击绿色的方框下载 下载后得到一个压缩包 解压后可以看到有两个文件 点击 msi进行安装 选
  • Json Object转Model, Model、DataTable转Json Object (Jayrock技巧)

    本文假定读者有一定的Ext 控件的使用经验 看过Ext EditGridPanel实现效果的朋友会很惊讶 一个Grid就能实现所有增删改查功能 在展示给客户看时 让你的表现得很风骚 而他们又怎么知道 我们在调试js时 是多么痛苦 如何在js
  • PyTorch基础练习-task5(PyTorch实现L1,L2正则化以及Dropout)

    PyTorch基础练习 task5 一 Dropout原理 二 用代码实现正则化 L1和L2 2 1 L1实现 2 2 L2实现 三 PyTorch中实现dropout 一 Dropout原理 在前向传播的时候 让某个神经元的激活值以一定的
  • android edittext 输入完成监听,EditText输入监听

    EditText输入监听 原创 6710766562015 05 13 13 34 38著作权 文章分类 android开发 阅读数 548 著作权归作者所有 来自51CTO博客作者671076656的原创作品 如需转载 请注明出处 否则将
  • 关于idea 生成war 包放入tomcat的路径访问问题

    目录 1 打包成war 2 关于war 和war exploded 3 在idea中使用tomcat启动 4 把war包放在指定的tomcat下启动 1 打包成war 点击右上角project structure或者左上角File proj
  • leetcode刷题(不邻接植花、电话号码的字母组合、统计共同度过的日子数、节点与其祖先之间的最大差值、分隔数组以得到最大和、二进制求和、x的平方根、最小偶倍数)

    目录 1 不邻接植花 2 电话号码的字母组合 3 统计共同度过的日子数 4 节点与其祖先之间的最大差值 5 分隔数组以得到最大和 6 二进制求和 7 x的平方根 8 最小偶倍数 1 不邻接植花 2 电话号码的字母组合 class Solut
  • LeetCode——二叉树

    二叉树 二叉树概念和性质 104 二叉树的的最大深度 递归 98 验证二叉搜索树 中序遍历 101 对称二叉树 代码比较精巧 不好理解 102 二叉树的层序遍历 中等 参考题解 自己码的代码 108 将有序数组转换为二叉搜索树 递归 剑指
  • 如何写好Java程序呢

    如何写出更好的Java代码 05 22 2014 Java是最流行的编程语言之一 但似乎并没有人喜欢使用它 好吧 实际上Java是一门还不错的编程语言 由于最近Java 8发布了 我决定来编辑一个如何能更好地使用Java的列表 这里面包括一