
编写java的软件使用教程:新手完成第一张作品的方法
第一次用 Java 做出一张可见的作品,不必先搭建大型图形项目,也不需要安装复杂的图像软件。本文使用 JDK 自带的 Java2D API,在内存中创建一张图片,绘制背景、圆形、矩形和文字,再将作品保存为 PNG 文件。
完成后,你会得到一个可以独立运行的 Java 程序,并知道如何编译、运行、检查输出,以及排查常见问题。示例面向 Java 入门者,代码兼容 Java 8 及以上版本,不依赖第三方库。
一、这类 Java 程序适合做什么
Java2D 适合绘制结构相对明确的二维图形,例如流程图、简单海报、图表、验证码原型、图标草稿,以及需要批量生成的 PNG 图片。它也适合练习 Java 的类、方法、变量和异常处理:运行程序后,结果会以图片文件的形式保存下来,便于查看。
本教程中的程序是一个简单的静态图片生成器。它不需要打开图形窗口,因此可以在没有桌面环境的服务器上运行;也可以作为更大项目中的一个绘图模块。它并不是专业图像编辑器,不提供图层面板、交互式画布、照片滤镜或复杂排版功能。若要处理大量高分辨率图像、制作动画或进行专业印刷,需要另外评估工具和内存需求。
二、准备 Java 环境
需要安装 JDK,而不仅是运行 Java 程序所需的运行环境。JDK 提供编译器 javac,本例需要用它把源代码编译成可运行的类文件。安装完成后,打开终端或命令提示符,执行以下命令检查环境:
java -version
javac -version
两条命令都应显示版本信息。如果系统提示找不到命令,通常是 JDK 没有安装,或安装目录没有配置到系统的 PATH 环境变量中。不同操作系统的安装步骤不完全相同,应以所选 JDK 发行版的说明为准。
新手可先将代码保存到一个普通目录,例如 Windows 的 C:\java-work,或 macOS、Linux 的 ~/java-work。目录路径尽量使用自己有写入权限的位置,避免把程序放在受保护的系统目录中。
三、编写第一张作品
新建文本文件,将文件名保存为 FirstArtwork.java。注意 Java 中 public 类的名称必须与源文件名一致,大小写也必须一致。将下面代码原样复制进去:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class FirstArtwork {
public static void main(String[] args) {
if (args.length > 1) {
System.err.println("用法:java FirstArtwork [输出文件路径]");
System.exit(2);
}
String outputPath = args.length == 1
? args[0]
: "first-artwork.png";
if (outputPath.trim().isEmpty()) {
System.err.println("输出文件路径不能为空。");
System.exit(2);
}
final int width = 800;
final int height = 600;
BufferedImage image = new BufferedImage(
width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
try {
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
// 背景
g.setColor(new Color(245, 247, 250));
g.fillRect(0, 0, width, height);
// 画布上的装饰圆
g.setColor(new Color(207, 226, 255));
g.fill(new Ellipse2D.Double(560, 70, 170, 170));
g.setColor(new Color(255, 220, 186));
g.fill(new Ellipse2D.Double(80, 390, 130, 130));
// 中央卡片
g.setColor(Color.WHITE);
g.fill(new RoundRectangle2D.Double(
120, 120, 560, 340, 28, 28));
// 卡片标题
g.setColor(new Color(35, 48, 68));
g.setFont(new Font("SansSerif", Font.BOLD, 34));
g.drawString("My First Java Artwork", 165, 205);
// 图形主体:太阳与地面
g.setColor(new Color(255, 190, 70));
g.fill(new Ellipse2D.Double(225, 250, 110, 110));
g.setColor(new Color(73, 160, 120));
g.fill(new RoundRectangle2D.Double(
365, 290, 190, 76, 18, 18));
// 说明文字
g.setColor(new Color(95, 108, 125));
g.setFont(new Font("SansSerif", Font.PLAIN, 18));
g.drawString("Created with Java2D", 165, 410);
} finally {
g.dispose();
}
File output = new File(outputPath);
try {
File parent = output.getAbsoluteFile().getParentFile();
if (parent != null && !parent.isDirectory()) {
System.err.println("输出目录不存在:" + parent);
System.exit(1);
}
boolean written = ImageIO.write(image, "png", output);
if (!written) {
System.err.println("当前 Java 环境没有可用的 PNG 写入器。");
System.exit(1);
}
System.out.println("作品已保存到:" + output.getAbsolutePath());
} catch (IOException e) {
System.err.println("保存图片失败:" + e.getMessage());
System.exit(1);
}
}
}
这段代码创建了一张 800×600 像素的透明通道图片,先用不透明颜色填满背景,再绘制装饰元素和文字。代码中的英文是图片上的文字,不影响程序运行;如果要改成中文,可以把字符串替换为中文,但实际显示效果取决于操作系统是否提供相应字体。
四、编译并运行
在终端中进入 FirstArtwork.java 所在目录。Windows 可以在文件夹地址栏输入 cmd 打开命令提示符,也可以使用 PowerShell;macOS 和 Linux 可打开终端并用 cd 切换目录。
先编译源文件:
javac FirstArtwork.java
编译成功时通常不会显示任何内容,并会在当前目录生成 FirstArtwork.class。然后运行程序:
java FirstArtwork
默认情况下,程序会在当前工作目录创建 first-artwork.png。注意“当前工作目录”是运行命令时终端所在的位置,不一定是源文件所在目录。程序会打印图片的绝对路径;可根据该路径打开文件确认结果。
也可以在运行时指定一个输出路径:
java FirstArtwork "output/my-artwork.png"
这里的 output 目录必须已经存在。程序不会自动创建目录;如果目录不存在或没有写入权限,会显示错误信息。路径包含空格时,应像上例一样用引号括起来。在 Windows 中,也可以使用带盘符的路径,例如:
java FirstArtwork "C:\Users\YourName\Pictures\my-artwork.png"
把 YourName 替换成实际用户名。Java 字符串中的反斜杠规则不适用于这里的命令行参数;这里输入的是操作系统命令,不是 Java 源代码字符串。
五、代码在做什么
1. 创建像素画布
BufferedImage 表示程序内存中的图片。构造方法接收宽度、高度和像素格式:
BufferedImage image = new BufferedImage(
width, height, BufferedImage.TYPE_INT_ARGB);
TYPE_INT_ARGB 使用包含透明度通道的像素格式。当前示例把整个背景填成不透明浅灰色,因此最终画面没有透明空白;如果删除背景填充,未绘制区域可能保持透明。输出格式使用 PNG,是因为 PNG 支持透明度且适合保存清晰的图形和文字。
2. 获取绘图对象并释放资源
image.createGraphics() 返回 Graphics2D,后续设置颜色、字体和绘制形状都通过它完成。绘图结束后调用 dispose() 释放图形上下文关联的资源。使用 try/finally 可以确保即使绘图过程中出现异常,也会执行释放操作。
3. 绘制形状和文字
setColor 设置接下来使用的颜色,fillRect 填充矩形,fill 则可以填充椭圆和圆角矩形等形状。坐标以图片左上角为原点,向右增加的是 x 坐标,向下增加的是 y 坐标。比如在坐标 (225, 250) 绘制一个宽、高均为 110 的椭圆。
drawString 的 x、y 坐标表示文字基线的位置,不是文字左上角。文字大小由 Font 控制,具体字体是否存在、渲染细节和中文回退字体可能因系统而异。抗锯齿设置可以让边缘看起来更平滑,但无法保证所有环境中的像素结果完全一致。
4. 写出 PNG 文件
ImageIO.write(image, "png", output) 将图片写入文件。方法返回 true 表示找到对应格式的写入器并完成写入;返回 false 表示没有合适的写入器。发生文件读写问题时,它会抛出 IOException,因此代码使用 try/catch 提示用户。
文件名扩展名并不会自动决定输出格式。本例始终使用 PNG 编码,所以即使指定路径以 .jpg 结尾,文件内容仍然是 PNG。为避免其他软件误判,应该让文件扩展名与格式一致,使用 .png。
六、可调整的内容与参数边界
新手可以先从改颜色、文字和形状坐标开始。例如,将 new Color(245, 247, 250) 中的 RGB 数值改成其他颜色;三个分量的范围都是 0 到 255。把文字参数换成自己的标题,或修改椭圆和圆角矩形的 x、y、宽度与高度,即可制作不同版式。
画布尺寸目前固定为 800×600,避免初学阶段同时处理命令行参数和资源限制。若要让尺寸可配置,需要先解析参数,并验证它们是正整数、没有超出应用允许的范围,再创建 BufferedImage。不应直接接受任意大的宽高:图像需要占用内存,像素数和内存开销会随宽、高乘积增加,还会有绘图对象和编码过程的额外开销。具体可用上限取决于堆内存、JDK、图片格式和运行环境,不存在适用于所有机器的统一安全尺寸。
本例只允许一个可选的位置参数;多传参数时会显示用法并以非零状态退出。位置参数可以是文件名或路径,但程序不会替用户创建目录,也没有限制路径只能位于某个固定文件夹。路径为空会被拒绝。除此之外,程序没有对路径做沙箱隔离或防止覆盖检查。
因此,运行前应确认目标路径正确,并确保输出目录可写。若目标文件已经存在,写入通常会覆盖它;不要把重要文件名直接作为输出目标。需要避免覆盖时,可自行增加“文件已存在则拒绝写入”的检查,或先让程序生成唯一文件名。该检查在并发运行等情况下仍需结合具体需求设计,不能仅凭一个简单判断保证所有场景下的原子性。
七、常见错误及排查方法
- 提示找不到
javac:先确认安装的是 JDK,再检查 PATH 是否包含 JDK 的可执行文件目录。重新打开终端后再次执行javac -version。 - 提示找不到主类:确认已在 class 文件所在目录执行命令,类名大小写正确,并且命令写成
java FirstArtwork,而不是把.class加到类名后面。 - 提示文件名和类名不一致:确认源文件严格命名为
FirstArtwork.java。Java 区分大小写,firstartwork.java不是同一个名称。 - 编译时出现非法字符或编码错误:将源文件保存为 UTF-8,并检查复制代码时是否混入全角引号、中文分号或格式化网页带来的特殊字符。Java 8 环境处理源文件编码时,也可显式指定
javac -encoding UTF-8 FirstArtwork.java。 - 提示输出目录不存在:先手动创建目录,或将参数改成当前目录下的文件名。本程序有意不自动创建目录,避免在意料之外的位置生成目录结构。
- 没有找到图片:查看程序打印的绝对路径,不要只在源代码所在文件夹里寻找。程序的相对路径以启动命令时的当前目录为基准。
- 文字显示为方框或字体不同:操作系统可能没有合适字体。可以检查系统字体,或选择更常见的字体名称;但字体回退和实际字形仍由运行环境决定。
- 图片被旧内容覆盖:程序会写入指定目标文件。运行前检查输出路径,必要时换一个文件名,并对重要文件提前备份。
八、安全与使用边界
本示例只在本地创建并写入一张图片,不会联网,不会读取用户指定的输入图片,也不会执行外部命令。它适合用来理解基本绘图和文件输出流程,但不能因此认为任意图片处理程序都安全。若后续加入用户上传的图片、网络图片或第三方文件,应考虑输入格式校验、文件大小限制、异常处理和资源消耗控制。
输出路径来自命令行参数,因此程序会按当前用户的文件权限尝试写入该位置。不要在不了解来源的情况下运行他人提供的参数或脚本;尤其不要在高权限账户下把不可信路径直接交给程序。将程序部署到服务端时,应把输出位置限制在服务预先指定的目录,并结合实际部署环境控制访问权限、文件覆盖和并发写入。
宽高、色彩和绘图坐标也需要与实际画布匹配。坐标超出画布时,超出部分通常不会出现在图片中;负数坐标也可能导致图形被裁切。对于来源不可信的尺寸参数,必须设置合理上限并处理整数溢出和内存耗尽风险。不要仅凭本地小图测试成功,就推断程序可以无约束地处理超大图片。
九、接下来可以怎样练习
第一步,替换标题和配色,观察每次修改后的图片变化。第二步,把重复的绘图代码整理成方法,例如创建专门负责绘制背景或卡片的方法。第三步,再增加经过校验的宽、高参数,并为允许范围设计符合实际用途的上限。若需要把程序用于批量制图,可进一步讨论输入数据格式、文件命名规则、异常记录和资源回收。
完成这张作品后,你已经走过了 Java 图形程序最基本的一条路径:准备 JDK、编写源文件、编译、运行、在内存中绘图,并将结果保存成文件。后续功能可以逐步叠加,但在增加复杂度之前,先确认输出路径、参数范围和错误提示符合使用场景,程序会更容易维护,也更不容易误覆盖文件或消耗过多资源。




