Skip to content

输出

Java提供的输出包括:System.out.println() / print() / printf()

其中printf()可以格式化输出

输入

Java提供Scanner对象来方便输入,读取对应的类型可以使用:

scanner.nextLine() / nextInt() / nextDouble() / ...

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in); // 创建Scanner对象
        System.out.print("Input your name: "); // 打印提示
        String name = scanner.nextLine(); // 读取一行输入并获取字符串
        System.out.print("Input your age: "); // 打印提示
        int age = scanner.nextInt(); // 读取一行输入并获取整数
        System.out.printf("Hi, %s, you are %d\n", name, age); // 格式化输出
    }
}

判断引用类型相等

在Java中,判断值类型的变量是否相等,可以使用==运算符。但是,判断引用类型的变量是否相等,==表示“引用是否相等”,或者说,是否指向同一个对象。例如,下面的两个String类型,它们的内容是相同的,但是,分别指向不同的对象,用==判断,结果为false

要注意浮点数判断相等不能直接用==运算符,浮点数在计算机中常常无法精确表示,并且计算可能出现误差,因此,判断浮点数相等用==判断不靠谱

java
public class Main {
    public static void main(String[] args) {
        double x = 1 - 9.0 / 10;
        if (x == 0.1) {
            System.out.println("x is 0.1");
        } else {
            System.out.println("x is NOT 0.1");
        }
    }
}

引用类型判断内容相等要使用equals(),注意避免NullPointerException

java
public class Main {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "HELLO".toLowerCase();
        System.out.println(s1);
        System.out.println(s2);
        if (s1.equals(s2)) {
            System.out.println("s1 equals s2");
        } else {
            System.out.println("s1 not equals s2");
        }
    }
}

for each

for循环相比,for each循环的变量n不再是计数器,而是直接对应到数组的每个元素。for each循环的写法也更简洁。但是,for each循环无法指定遍历顺序,也无法获取数组的索引。

java
public class Main {
    public static void main(String[] args) {
        int[] ns = { 1, 4, 9, 16, 25 };
        for (int n : ns) {
            System.out.println(n);
        }
    }
}

二维数组

java
for (int[] arr : ns) {  //arr 对应每个ns[]的元素
    for (int n : arr) { //n再对应arr[]中的每个元素
        System.out.print(n);
        System.out.print(', ');
    }
    System.out.println();
}

打印多维数组可以使用 Arrays.deepToString()

命令行参数

面向对象编程

java
public class Main {
    public static void main(String[] args) {
        City bj = new City();
        bj.name = "Beijing";
        bj.latitude = 39.903;
        bj.longitude = 116.401;
        System.out.println(bj.name);
        System.out.println("location: " + bj.latitude + ", " + bj.longitude);
    }
}
class City {
     public String name;
     public double latitude;
    public double longitude;
}

定义方法

从上面的代码可以看出,定义方法的语法是:

java
修饰符 方法返回类型 方法名(方法参数列表) {
    若干方法语句;
    return 方法返回值;
}

继承

  • 继承是面向对象编程的一种强大的代码复用方式;

  • Java只允许单继承,所有类最终的根类是Object;(可以套娃实现多继承)

  • protected允许子类访问父类的字段和方法;

  • 子类的构造方法可以通过super()调用父类的构造方法;

  • 可以安全地向上转型为更抽象的类型;

  • 可以强制向下转型,最好借助instanceof判断;

  • 子类和父类的关系是is,has关系不能用继承。

  • final修饰的类不能被继承

  • 对于一个类的实例字段,同样可以用final修饰。用final修饰的字段在初始化后不能被修改。例如:

    java
    class Person {
        public final String name = "Unamed";
    }

    final字段重新赋值会报错:

    jade
    Person p = new Person();
    p.name = "New Name"; // compile error!

​ 可以在构造方法中初始化final字段:

java
class Person {
    public final String name;
    public Person(String name) {
        this.name = name;
    }
}

这种方法更为常用,因为可以保证实例一旦创建,其final字段就不可修改

image-20220104165027577

多态

  • 成员方法:编译看左边,执行看右边
  • 成员变量:编译看左边,执行看左边

​ ---为什么 成员变量成员方法 的访问不一样呢? ​ 因为 成员方法 有重写,而 成员变量 没有。

抽象类

抽象类和抽象方法必须使用 abstract关键字修饰

public abstract class 类名 {}

public abstract void eat();

抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类

抽象类不能实例化

​ 抽象类如何实例化呢?参照多态的方式,通过子类对象实例化,这叫抽象类多态

抽象类的子类

​ 要么重写抽象类中的所有抽象方法

​ 要么是抽象类

抽象类的成员特点

成员变量可以是变量,也可以是常量 构造方法有构造方法,但是不能实例化

例:

java
Animal a = new Animal()

那么,构造方法的作用是什么呢?s

用于子类访问父类数据的初始化

成员方法

可以有抽象方法:限定子类必须完成某些动作 也可以有非抽象方法:提高代码复用性

接口

  • 接口用关键字 interface 修饰

    java
     public interface 接口名 {}
  • 类实现接口用 implements表示

    java
      public class 类名 implements 接口名 {}
  • 接口不能实例化

    接口如何实例化呢?

    ​ 参照多态的方式,通过实现类对象实例化,这叫接口多态

    多态的形式:具体类多态,抽象类多态,接口多态

  • 多态的前提

    有继承或者实现关系;有方法重写;有父(类/接口) 引用指向(子/实现)类对象

  • 接口的实现类

    要么重写接口中的所有抽象方法

    要么是抽象类

获取网页内容

java
import java.io.IOException;
import java.net.URL;
import java.util.Scanner;
public class ReadingWebPage {
   public static void main(String args[]) throws IOException {
      //实例化URL类
      URL url = new URL("http://myip.ipip.net/");
      //检索指定页面的内容
      Scanner sc = new Scanner(url.openStream());
      //实例化StringBuffer类以保存结果
      StringBuffer sb = new StringBuffer();
      while(sc.hasNext()) {
         sb.append(sc.next());
         //System.out.println(sc.next()); 
      }
      //从字符串缓冲区对象中检索字符串
      String result = sb.toString();
      result = new String(result.getBytes("gbk"),"utf-8"); //转换编码格式
      System.out.println(result);
      //删除HTML标签
      result = result.replaceAll("<[^>]*>", "");
      System.out.println("Contents of the web page: "+result);
   }
}

下载

java
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

public class Test {
    /**
     * 从网络Url中下载文件
     *
     * @param urlStr
     * @param fileName
     * @param savePath
     * @throws IOException
     */
    public static String downLoadFromUrl(String urlStr, String fileName, String savePath) {
        try {

            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            // 设置超时间为3秒
            conn.setConnectTimeout(3 * 1000);
            // 防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

            // 得到输入流
            InputStream inputStream = conn.getInputStream();
            // 获取字节数组
            byte[] getData = readInputStream(inputStream);

            // 文件保存位置
            File saveDir = new File(savePath);
            if (!saveDir.exists()) {
                saveDir.mkdir();
            }
            File file = new File(saveDir + File.separator + fileName);
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(getData);
            if (fos != null) {
                fos.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
            // System.out.println("info:"+url+" download success");
            return saveDir + File.separator + fileName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";

    }

    /**
     * 从输入流中获取字节数组
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }


    public static void main(String[] args) {

        downLoadFromUrl("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3363295869,2467511306&fm=26&gp=0.jpg",
                "1.jpg","E:\\");
    }
}

执行cmd

java
import java.io.BufferedReader;

import java.io.InputStreamReader;



/**

 * 执行windows的cmd命令工具类

 * @author dufei

 *

 */

public class CMDUtil {



  /**

   * 执行一个cmd命令

   * @param cmdCommand cmd命令

   * @return 命令执行结果字符串,如出现异常返回null

   */

  public static String excuteCMDCommand(String cmdCommand)

  {

    StringBuilder stringBuilder = new StringBuilder();

    Process process = null;

    try {

      process = Runtime.getRuntime().exec(cmdCommand);

      BufferedReader bufferedReader = new BufferedReader(

          new InputStreamReader(process.getInputStream(), "GBK"));

      String line = null;

      while((line=bufferedReader.readLine()) != null)

      {

        stringBuilder.append(line+"\n");

      }

      return stringBuilder.toString();

    } catch (Exception e) {

      e.printStackTrace();

      return null;

    }

  }

  /**

   * 执行bat文件,

   * @param file bat文件路径

   * @param isCloseWindow 执行完毕后是否关闭cmd窗口

   * @return bat文件输出log

   */

  public static String excuteBatFile(String file, boolean isCloseWindow)

  {

    String cmdCommand = null;

    if(isCloseWindow)

    {

      cmdCommand = "cmd.exe /c "+file;

    }else

    {

      cmdCommand = "cmd.exe /k "+file;

    }

    StringBuilder stringBuilder = new StringBuilder();

    Process process = null;

    try {

      process = Runtime.getRuntime().exec(cmdCommand);

      BufferedReader bufferedReader = new BufferedReader(

          new InputStreamReader(process.getInputStream(), "GBK"));

      String line = null;

      while((line=bufferedReader.readLine()) != null)

      {

        stringBuilder.append(line+"\n");

      }

      return stringBuilder.toString();

    } catch (Exception e) {

      e.printStackTrace();

      return null;

    }

  }

 

  /**

   * 执行bat文件,新开窗口

   * @param file bat文件路径

   * @param isCloseWindow 执行完毕后是否关闭cmd窗口

   * @return bat文件输出log

   */

  public static String excuteBatFileWithNewWindow(String file, boolean isCloseWindow)

  {

    String cmdCommand = null;

    if(isCloseWindow)

    {

      cmdCommand = "cmd.exe /c start"+file;

    }else

    {

      cmdCommand = "cmd.exe /k start"+file;

    }

    StringBuilder stringBuilder = new StringBuilder();

    Process process = null;

    try {

      process = Runtime.getRuntime().exec(cmdCommand);

      BufferedReader bufferedReader = new BufferedReader(

          new InputStreamReader(process.getInputStream(), "GBK"));

      String line = null;

      while((line=bufferedReader.readLine()) != null)

      {

        stringBuilder.append(line+"\n");

      }

      return stringBuilder.toString();

    } catch (Exception e) {

      e.printStackTrace();

      return null;

    }

  }

  public static void main(String[] args) {

    String cmd = "i";

    String result = CMDUtil.excuteCMDCommand(cmd);

    System.out.println(result);

  }

}

springBoot

yml 配置文件

@Value ("${键名}")

@ConfigurationProperties(prefix="前缀") 要求类中的变量名于yml中的键名相同

mapper

sql
@Select("select * from user where email = #{username}")
sql
@Insert("INSERT INTO users (email, password) VALUES (#{username}, #{cipherPwd});")

参数校验

java
    public Result register(
            @RequestParam("email")
            @Pattern(regexp = EMAIL_REGEX, message = "邮箱格式不正确")
            String username,
            @RequestParam("password")
            @Pattern(regexp = PASSWORD_REGEX, message = "密码格式不正确")
            String password)

指定请求参数对应的变量名

注解

字段名

如果 JSON 字段名与 Java 对象的字段名不一致,你可以使用 Jackson 的注解来解决这个问题。特别是可以使用 @JsonProperty 注解来映射 JSON 字段到 Java 字段。以下是一个示例:

假设你的 JSON 数据如下:

json
json{
    "full_name": "John",
    "user_age": 30,
    "email_address": "john@example.com"
}

你可以定义一个 Java 实体类,并使用 @JsonProperty 注解来映射 JSON 字段名到 Java 字段名:

java
@JsonProperty("full_name")
    private String name;
    
@JsonProperty("user_age")
    private int age;
    
@JsonProperty("email_address")
    private String email;

@Data 是 Lombok 库中的一个注解,用于自动为类生成各种常用方法,包括 getter、setter、equals、hashCode 和 toString 方法。这大大简化了 Java 类的编写,你不再需要手动编写这些方法。

@Pattern 注解用于对字符串进行正则表达式的校验。

@Digits(integer = 5, fraction = 0) 指定了必须为最多五位的整数。

@JsonIgnore 是 Jackson 库的一个注解,用于在 JSON 序列化/反序列化时忽略某个属性。

@JsonFormat 是 Jackson 库提供的一个注解,它可以用于指定 Java 对象序列化为 JSON 时的格式。

在反序列化时不忽略,但在序列化时忽略

@JsonIgnore注解是Jackson库提供的,用于在JSON序列化/反序列化过程中忽略该属性,而@NotEmpty注解是Java Bean Validation(JSR 380)提供的,用于验证该属性在处理过程中不能为空。

如果你在反序列化(即,从JSON转换为Java对象)时需要这个字段,但在序列化(即,从Java对象转换为JSON)时不希望这个字段出现,那么可以使用Jackson的@JsonInclude@JsonProperty注解来分别控制序列化和反序列化的行为:

java
@NotEmpty
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String cxPassword;

在这段代码中,@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)告诉Jackson在序列化时忽略这个字段(即,不将这个字段转换为JSON),但在反序列化时包含这个字段(即,从JSON转换为Java对象时,这个字段的值会被设置)。这样,你就可以在保证数据安全性的同时,满足数据验证的需求。

WRITE_ONLY:仅做反序列化操作。 READ_ONLY:仅做序列化操作。

日期格式化

例如,你可以使用 @JsonFormat 来改变日期的序列化格式:

java
public class Event {
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
    private Date eventDate;
    //...
}

Validation的注解

@JsonIgnore import com.fasterxml.jackson.annotation.JsonIgnore; 让springmvc把对象转换成json字符串的时候,忽略该属性,最终json字符串中就没有这个属性了

@NotNull 值不能为null

@NotEmpty 值不能为null,并且内容不能为空

@Email 满足邮箱格式

配置文件

yml
mybatis:
  configuration:
    map-underscore-to-camel-case: true # 驼峰命名转换

拦截器

java
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle method is Running");
        return true; // 返回true才会继续向下执行,返回false则取消当前请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle method is Running");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion method is Running");
    }
}

这个拦截器的 preHandle 方法在请求处理之前被调用,如果它返回 true,那么请求继续被处理,否则请求被取消。postHandle 方法在请求处理之后,但在视图渲染之前被调用。afterCompletion 方法在请求处理完毕之后被调用,即在视图渲染之后。

然后,你需要在你的 Spring 配置中注册这个拦截器。如果你使用的是 Java 配置,你可以通过覆盖 WebMvcConfigureraddInterceptors 方法来做到这一点:

java
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor());
    }
}

自动添加参数

你可以使用 Spring 的拦截器(Interceptor)来自动添加 email 参数。拦截器可以在请求处理之前或之后添加特定的操作,这正是你需要的。

你可以创建一个拦截器,然后在 preHandle 方法中获取 email,并将其添加到请求的属性中。然后,在你的控制器方法中,你可以使用 @RequestAttribute 注解来获取这个 email 属性。

这是一个简单的拦截器示例:

java
@Component
public class EmailInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Map<String, String> map = ThreadLocalUtil.get();
        String email = map.get("email");
        request.setAttribute("email", email);
        return true;
    }
}

然后,你需要将这个拦截器添加到你的拦截器注册表中:

java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private EmailInterceptor emailInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(emailInterceptor).addPathPatterns("/cxAcct/**");
    }
}

最后,在你的控制器方法中,你可以使用 @RequestAttribute 注解来获取 email

java
@PostMapping("/bind")
public Result bind(@RequestBody @Validated CxAccount account, @RequestAttribute("email") String email) {
    int loginType = account.getLoginType();
    String username = account.getCxUsername();
    String password = account.getCxPassword();
    return chaoxingService.bind(email, loginType, username, password);
}

这样,你就可以在所有的 /cxAcct 路径下的方法中自动获取 email 参数,而不需要每次都手动从 ThreadLocalUtil 中获取。

Released under the MIT License.