一文带你入门Java(万字长文,建议收藏)

简介: 一文带你入门Java(万字长文,建议收藏)

前言

本章节主要讲述java的一些基础语法,比如常见的数据类型,流程控制语句,类的一些属性和方法,帮助大家理解和快速入门。如果你已经对jav很熟悉了,可以跳过本章节的内容。


java简单介绍

Java是一门面向对象 编程语言, Javas是静态语言。Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等。


这里简单说一下什么是静态语言,什么是动态语言?

  • 静态语言,比如java它需要编译成机器码,才能够被计算识别可运行,因为计算机只能看懂二进制。
  • 动态语言,不需要我们手动去编译,它可以直接去运行我们的代码文件,比较典型的python,js这种脚本语言。


其实动态语言它本身内置了一个解释器,它通过解释器去完成我们的编译工作,所以我们感知不到。


::: tip 所谓工欲善其事,必先利其器,选择好的开发工具,能提升我们的开发体验。建议大家使用 jetbrains的 idea 开发工具来开发java应用, 目前大部分开发者都会选择使用它,非常的方便, 后边我会出一篇文章专门来讲一下,如何配置我们的idea工具,使得它更加强大。 :::


下载idea

进入官网后,直接点击 download 进行下载,浏览器会自动判断你的当前操作系统,选择 Ultimate版本,另一个版本是社区版,我们选择专业版。下载完成后点击安装。


默认它是一个纯英文的界面, 我们也可以通过安装汉化插件,点击 设置 -> 插件 -> 搜索(Chinese (Simplified) Language Pack / 中文语言包) 进行安装即可, 重启后会看到中文界面了。


配置JDK

我们可以直接通过idea来下载jdk,也可以通过 官网 来下载, 这里我们使用idea来下载jdk, 官网下载现在好像要注册账号了,有点小麻烦。打开idea,点击新建项目, 我们选择maven来新建项目, maven 是java的一种包管理工具,能够很方便的帮助我们构建项目,我们开发项目可能会引用一些成熟的第三方库,这时候我们就可以用简单的配置就可以把库引进来,想了解更多,可以到它的 官网 。选择好了以后,跟着以下步骤来搭建我们的环境:

  • 点击项目sdk, 这时候会发现是空的
  • 点击下载jdk, 版本我们选择1.8, 供应商我们选择 亚马逊 Corretto, 位置我们可以默认。下载好了以后,会自动帮我们选择刚刚下载的jdk
  • 点击下一步, 项目名和项目所在位置可以自定义, 好了以后点击完成,会自动打开项目


目录结构说明

  • pom.xml 这个文件存在于根目录, 主要用于配置maven的构建信息,学习基础部分,我们可以暂时不用管它。


  • src 这个目录主要用于放我们编写的源码,下边有一个java 和 resource 的目录,java存放我们的代码,resource主要放一些资源,比如配置文件这些,暂时可以不用管它。


为了规范,这些目录和文件不要去重命名或者其它更改, 如果改动, idea已经足够智能提醒我们不要乱改命名。


JDK是什么?

jdk(Java Development Kit),从字面意思翻译过来就是java开发的工具。打个比喻,我们打游戏之前需要安装一个软件,然后我们才能打开和操作它。那么jdk你也可以理解是一个软件,它用来帮助我们编写代码。这里还好引申另外两个名词, JRE和JVM。

JRE 顾名思义是java运行时环境,包含了java虚拟机,java基础类库。是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的。JDK包含了JRE,同时还包含了编译java源码的编译器javac。JRE根据不同操作系统, 提供不同的运行时环境,所以java它也是跨平台的语言。


JVM是Java Virtual Machine(Java虚拟机) 的缩写。它是java运行环境的一部分,是一个虚构出来的计算机,它是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM是用来解析和运行Java程序的。


hello world

我想要输出一句 ”你好, 憨憨“, 怎么搞? 这就安排。 首先在java目录新建一个文件,一个程序要跑起来,首先要有入口, 这个入口就是一个main方法,在java中,需要写在类中:

public class BaseMain {
   public static void main(String[] args) {
      System.out.println("你好, 憨憨");
   }
}
复制代码


点击绿色的箭头就可以运行了,因为idea已经帮我们把环境基础起来了,所以直接run

为了后续方便调试,我们常会在控制台输出信息,所以在新建一个Log类:

public class Log {
    public static void info(Object s) {
        System.out.println(s);
    }
}
复制代码


然后修改我们的main方法, static修饰的方法可以直接 类名 + 方法名去调用:

public class BaseMain {
   public static void main(String[] args) {
      Log.info("你好, 憨憨");
   }
}
复制代码

好了,你学废了吗?


基本数据类型

数据类型,顾名思义就是数据的类型,什么是数据?举个例子,你在使用网站时,密密麻麻的文字和图片就是数据,而他们的载体,比如文字它就是字符类型,我们通常叫它为字符串,我们看到的视频,图片这种二进制数据,通常是byte类型。我们通过各种类型的数据在一起计算交互,最终实现我们的程序。


java有 8 种数据类型,分别是:

  • boolean (1/8个字节1位)
  • char (2个字节16位)
  • byte (1个字节8位)
  • short (2个字节16位)
  • int (4个字节32位)
  • long (8个字节64位)
  • float (4个字节32位)
  • double (8个字节64位)


float 与 double:

// float a = 1.1; 1.1是字面量 这样会使得向下转型,会丢失精度
// 正确的写法:
float a = 1.1f;
double b = 1.1;
复制代码


隐式转换:

short c = 1;
  // 1是int型  精度比short高 没发隐式的向下转型成short
  // 这样可以达到隐式转换的目的
  c ++; // c = (short) (c + 1);
复制代码


流程控制

我们说话的时候会有逻辑语句,程序也一样,有了它,就能控制程序在设定中运行,举个例子, “如果我教你写java, 你就做我女朋友”


在java中用 if 表示:

// 这里的true是boolean类型, 在数学中叫真,相反的是 false
if(true) {
  Log.info("做我女朋友");
}
复制代码


如果她拒绝了咋办? 并对你说了句 "go out !", 在java中用 else 表示否则的意思,类似转折语句:

if(true) {
  Log.info("做我女朋友");
}else {
  Log.info("滚");
}
复制代码


你还不想放弃,我在外加请你吃饭+看电影, 在java中我们可以用 else if 这么表示, 类似二次转折:

// 第1层判断
if(教你写代码) {
  Log.info("做我女朋友");
  // 第2层判断
}else if(吃饭) {
  Log.info("做我女朋友");
  // 第3层判断
}else if(看电影) {
  Log.info("做我女朋友");
}else {
  // 第4层判断
  Log.info("滚");
}
复制代码


在你的不断努力下,她终于答应跟你吃饭了,这时候你要开始想了一下预算,那么预算可能会有很多种。在java中使用 switch来进行多种判断,为啥不是if,if也可以,但是多起来会导致if多层嵌套,不利于代码维护。说不定你下次改bug你都不知道写了啥。


当然也不完全是 switch 我们可以拆分方法,类等等。这里为了熟悉语法:

::: tip 支持的判断类型 : 需要 char、byte、short、int、Character、Byte、Short、Integer、String 或枚举 不支持: long、float、double :::

// 假设cost 为int型, 意思是花费
switch(cost) {
  case 200:
    Log.ingo("吃肯德基");
    // break 意思是跳出循环 
    break;
  case 100:
    Log.ingo("汉堡王");
    break;
    // default: 当以上条件不满足的时候会默认执行这个语句
  default:
    Log.ingo("吃煎饼果子");
    break;
}
复制代码


还是刚刚的例子, 吃完饭后,准备看电影,女神说了到10点,看没看完都回家,这时候你一直盯着看时间,生怕时间到了,中途你还上了个厕所, 忘了数数了。实际上这是一种循环的场景,一直在检测某一环节下满足某种条件时,执行对应的任务,在java中我们通常用 while 来表示,while类似当...什么时候。

# 没到十点 会一直执行
while(没到十点) {
  // 配合if 实现, 跳出循环
  if(十点到了) { 
    break;
  }
  // 上厕所 忘了看时间了
  if(上厕所) {
    // continue 表示跳出当前这个时刻,但不会终止循环, 下一次还是接着数数
    continue;
  }
  Log.info("还剩.xx.分钟")
}
复制代码


然后时间到了,你们一起走在回家的路上,心想,出都出来了,至少拉一次手, 最终成功了。这种场景属于。这种场景属于,不管失败与否,事件都会执行一次,在Java中用  **do ... while:

do {
  Log.info("拉手)
} while(false)
复制代码

最终女神跟你说了句:“你是好人”,你听了之后感动的哭了。


包装类型

前方高能, 如果你是小白,可能看的会有点糊涂 ~

基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成, 这里介绍常用的包装类型, 他们属于引用类型,因为他们本身也是一个对象


Integer

通常用于整数形,举个例子:

Integer x = 2;     // 装箱 调用了 Integer.valueOf(2)
 int y = x;         // 拆箱 调用了 X.intValue()
复制代码


Integer内部有一个缓冲池,缓冲池可以有效的帮我们缓存对象,从而减少对象的频繁创建, Java 8 中,Integer 缓存池的大小默认为 -128~127 我们可以通过源码可以看到:

// range [-128, 127] must be interned (JLS7 5.1.7)
 assert IntegerCache.high >= 127;
复制代码


其中 java new Integer(123) 相当于新建一个对象, 当我们再调用 java Integer.valueOf(123) 引用的就是同一个对象 。此外, Integer 不可被继承, 因为它的类是final修饰的。


** valueOf() ** 方法的实现, 先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容, 对应的源码如下:

public static Integer valueOf(int i) {
    if (i >= Integer.IntegerCache.low && i <= Integer.IntegerCache.high)
        return Integer.IntegerCache.cache[i + (-Integer.IntegerCache.low)];
    return new Integer(i);
}
复制代码


看到这里, 通过一个例子来感受一下:

Integer a = new Integer(123);
  Integer b = Integer.valueOf("123");
  Integer c = Integer.valueOf(123);
  System.err.println(a == b); // false
  System.err.println(a == c); // false
  System.err.println(c == b); // true
  // 自动装箱, 编译器会自动调用 valueOf
  Integer d = 123;
  Integer e = 124;
  Integer f = 123;
  System.err.println(d == e); // false 因为值不一样
  System.err.println(f == d); // true
复制代码


我们说默认的缓冲池大小为 -128~127 ,那么如果超过了怎么办。从源码看,内部会根据传进去的 i 进行 动态扩容

// 源码部分:
private static class IntegerCache {
 static final int low = -128;
 static final int high;
 static final Integer cache[];
 static {
   // high value may be configured by property
   int h = 127;
   String integerCacheHighPropValue = 
   sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
   if (integerCacheHighPropValue != null) {
       try {
           int i = parseInt(integerCacheHighPropValue);
           i = Math.max(i, 127);
           // Maximum array size is Integer.MAX_VALUE
           h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
       } catch( NumberFormatException nfe) {
           // If the property cannot be parsed into an int, ignore it.
       }
   }
   high = h;
   cache = new Integer[(high - low) + 1];
   int j = low;
   for(int k = 0; k < cache.length; k++)
       cache[k] = new Integer(j++);
   // range [-128, 127] must be interned (JLS7 5.1.7)
   assert Integer.IntegerCache.high >= 127;
 }
 private IntegerCache() {}
} 
复制代码


String

该类型通常用于表示字符串对象, 和Integer一样,它也是final修饰的不可继承, 源码定义如下:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    // java8: 使用char数组
    private final char value[];
    // 使用final修饰的数组 可以保证 String 不可变
    // java 9
    private final byte[] value;
  }
复制代码


我们可以看到初始值char数组是用finnal稀释的,这样保证  String对象 不可变的好处是什么?

  • 可以作为 hash的 key, 可以让hash值也不可变, 只需进行一次计算, 可以防止key重复, 在map取值的时候 会通过计算,hashCode() 和 equals来判断key, 而String的hashCode是根据 char[]数组内容来计算得到的散列码,如果相同的内容下,那么key是不可变的
  • String的缓存池, 如果一个String被创建过了,   再次获取可以从缓存池中获取,如果String可变的话 就没法使用缓存池了
  • 安全性。 String常用做参数
  • 天生线程安全 因为它不可变


String, StringBuffer and StringBuilder 三者联系?我们通过以下几点进行比较:

  • 可变性:
  • String 不可变 (不可变只的是本身不可变, 本质上它的操作都会产生新的Object)
  • StringBuffer and StringBuilder 可变 ( 并不会产生新的Object ,利用的是缓存池)
  • 线程安全:
  • String(通过finnal), StringBuffer(通过 synchronized进行同步 )
  • StringBuilder 不是线程安全的
  • 使用场景:
  • String 适合不需要频繁修改字符串
  • StringBuilder 优先使用,频繁修改字符串时
  • 在考虑多线程共享变量时使用 StringBuffer
  • 继承关系:
  • StringBuffer,StringBuilder 都继承了 AbstractStringBuilder
  • StringBuffer,StringBuilder,String 都不可被继承


我们说 Integer 有缓冲池,那么String是不是也有呢?答案是有的。我们通常叫它 常量池


在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到堆中,这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误, 不懂啥代的可以先放放,这属于jvm的环节,后边会给大家介绍。


String.intern() 方法: 如果字符串常量池包含了这个String对象,则直接返回该对象, 否则重新生成对象, 并返回, 举个例子:

StringBuilder a = new StringBuilder("hello");
  StringBuilder b = new StringBuilder("hello");
  StringBuilder c = a.append("");
  System.out.println(a == b); // false 两个new 不同对象
  System.out.println(a == c); // true append操作同一个对象
  String x = a.toString().intern();
  String y = b.toString().intern();
  Log.info("x ----- y");
  Log.info(x == y); // true
  // 原因:
  // String.intern 操作会把 a 字符串放到String pool 并返回字符串的引用
  // b.intern操作 会去String pool中获取 发现字符串一样,所以直接返回 a的引用
  String z = "hello";
  String m = "hello";
  Log.info(x == y); // true
  // 直接使用字面量创建时, 会自动加入 String Pool中
复制代码


这里引申一个面试题, 答案直接贴给大家:

String java = new StringBuilder("ja").append("va").toString();
  Log.info(java); // java
  Log.info(java == java.intern()); // true
  String go = new StringBuilder("g").append("o").toString();
  Log.info(go); // go
  Log.info(go == go.intern()); // true
  String java1 = new StringBuilder("ja").append("va").toString();
  Log.info(java1);   // java
  Log.info(java1 == java1.intern());  // false
复制代码


上述string builder ,进行类加载后, 调用的时候内部默认会生成一个java的String 对象(java jdk 自身的原因, sum.misc.Version 类注入常量池 )


关于 new String

这种方式创建字符串会获得两个对象,

  • 编译时期 存在String Pool 指向 String的字面量
  • 存在堆中的 String对象


以下是 String 构造函数的源码,可以看到,在将一个字符串对象作为另一个字符串对象的构造函数参数时,并不会完全复制 value 数组内容, 而是都会指向同一个 value 数组。

private final char value[];
  public String(String original) {
      this.value = original.value;
      this.hash = original.hash;
  }
复制代码


没关系,代码能跑就行 ~


面向对象

面向对象 是一种编程思想,不仅仅在java,其它语言可以,通过这种方法轮,我们可以编写利于维护的代码,让我们的代码更加条理,更加的有艺术,有了它,后来又引入了 java设计模式, 它也是一种编程方法, 可以把它理解为语文中的写作方法。


面向对象和面向过程?

网上介绍的也很多,但是介绍的有点复杂, 这里给大家提炼几个关键字:

面向对象 : 谁做了某件事 (主体对象是谁)

面向过程:  做了谁的某件事 (没有主体对象,一股劲的做)


类和方法

在java中,我们用来实现面向对象,我们用java描述一个苹果对象:

class Apple {
  Sting color;
}
复制代码


上面定义了一个Apple类,内部有一个color的属性,如果我们一开始想要红色的苹果,在java中可以使用构造函数:

class Apple {
  Sting color;
  // 完成初始化
  Apple(String color) {
      this.color = color;
  }
}
复制代码


想后期改颜色怎么办, 我们可以使用类的方法:

class Apple {
  Sting color;
  // 完成初始化
  Apple(String color) {
      this.color = color;
  }
 // 方法
 // void指定的是返回值的类型, 用void表示无返回值
  public void setColor(String color) {
      this.color = color;
  }
}
复制代码


如果想用两个颜色怎么办, 我们可以利用方法的重载, 在声明一个方法:

::: tip重载: 存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。


重写: @Override 存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法。 :::

class Apple {
  Sting color;
  // 完成初始化
  Apple(String color) {
      this.color = color;
  }
 // 方法1
  public void setColor(String color) {
      this.color = color;
  }
// 方法2
  public void setColor(String color, String color) {
      this.color = color;
  }
}
复制代码


好了有了类, 如何使用它?首先要实例化:

// 实例
Apple apple = new Apple("red");
// 调用实例方法
apple.setColor("green");
复制代码


类的继承

继承顾名思义,继承类的一些属性和方法,举个例子, 还是刚刚的水果。java中使用 extends :

// 水果类
class Furit {
  Sting color;
  // 完成初始化
  Apple(String color) {
      this.color = color;
  }
  public void setColor(String color) {
      this.color = color;
  }
}
// 苹果类, 继承水果类
class Apple extends Furit {
  // ....
}
// 橘子类, 继承水果类
class Orange extends Furit {
  // ....
}
复制代码


方法重写

使用 @Override 来重写方法

class Orange extends Furit {
  @Override
  public void setColor(String color) {
      this.color = color;
  }
}
复制代码


接口

  • 可以看成是完全的抽象类, java8之前 不能有方法实现, java8之后可以实现, 为了减少维护成本
  • 接口内部的成员 默认都是public, 并且不允许定义为 private 和 protected  java9之后允许定义private
  • 接口的字段默认都是final 和 static 的
  • 实现接口的方法通过 implements 关键字
  • 接口直接也可以继承


接口的好处: 一个类可以实现多个接口, 但是不能继承多个抽象类, 接口主要用于约束类的一些行为,举个例子:

public interface Food {
  void eat(); 
}
public class User implements Food {
  // 必须实现接口的方法,不然会报错
  public void eat() {
  }
}
复制代码


接口之间也有继承:

public interface Food {
  void eat(); 
}
public interface Food extends Food {}
复制代码


类中的关键词

在之前的介绍中经常会看到 public ,static之类的,现在我们就一一介绍它:


final

修饰变量时:

  • 作为常量, 可以是运行时常量也可使编译时常量, 不可改变
  • 作为引用对象,不可以修改引用, 但可以修改本身的值


修饰方法时:

  • 不能够被重写, 其中private是隐式的final


修饰类时:

  • 不能够被继承


static

修饰变量:

  • 所有实例共享静态变量 ,在内存中只存一份, 可以通过 class.name 访问
  • 实例变量,每创建一个实例就会产生一个实例变量,与实例共存亡


静态方法:

  • 静态方法在类加载的时候就存在了,不依赖任何实例, 必须有实现 不能是抽象方法
  • 内部方法访问时 只可以访问static修饰的变量和方法,不能有this super关键字


静态语句块:

  • 在类加载的时候值只运行一次
static {
    //....
}
复制代码


静态内部类: (static 不能修饰外部类)

  • 静态内部类不能访问外部类非静态成员
  • 创建不需要依赖外部类的实例化
public class OuterClass {
  class InnerClass {
      int x;
  }
  public String get() {
      return InnerClass.x;  // 可以直接访问内部类的成员
  }
  static class StaticInnerClass {
  }
  public static void main(String[] args) {
      // InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context
      OuterClass outerClass = new OuterClass();
      InnerClass innerClass = outerClass.new InnerClass();
      StaticInnerClass staticInnerClass = new StaticInnerClass();
  }
}
复制代码


静态导包:在使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低。

import static com.xxx.ClassName.*
复制代码


private

这个主要用于修饰私有属性和方法, 只能在本类中访问


public

公开权限, 表明该成员变量和方法是共有的,能在任何情况下被访问


protected

必须在同一包中才能被访问


类的初始化顺序

静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。


存在继承的情况下,初始化顺序为: 父优子 静优实

  • 父类(静态变量、静态语句块)
  • 子类(静态变量、静态语句块)
  • 父类(实例变量、普通语句块)
  • 父类(构造函数)
  • 子类(实例变量、普通语句块)
  • 子类(构造函数)


对象的通用方法

//    public native int hashCode()
//
//    public boolean equals(Object obj)
//
//    protected native Object clone() throws CloneNotSupportedException
//
//    public String toString()
//
//    public final native Class<?> getClass()
//
//    protected void finalize() throws Throwable {}
//
//    public final native void notify()
//
//    public final native void notifyAll()
//
//    public final native void wait(long timeout) throws InterruptedException
//
//    public final void wait(long timeout, int nanos) throws InterruptedException
//
//    public final void wait() throws InterruptedException
复制代码

我们介绍常用的几个:


equals 用于判断等价关系

  • 任何非null的对象与null 比较都为 false
  • 基本类型: == 判断值 , 没有equals方法
  • 引用类型: == 判断两个变量是否引用同一个对象 , equals判断引用的对象是否等价
public static void main() {
    Log.info("1".equals(1)); // false
    Log.info("--------->"); // false
    Integer a = 1;
    Integer b = 1;
    Integer c = new Integer(1);
    Log.info(a.equals(b)); // true 1 == 1
    Log.info(a == b); // true  引用的是同一个对象, 原因是Integer缓冲池
    Log.info(a == c); // false new 关键词生成的新对象所以引用不同
    Log.info(a.equals(c)); // true  他们引用的对象值都是1 所以相等
}
复制代码


手动实现一个equals,在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象哈希值也相等

  • 判断是否引用同一个对象 是 -> true
  • 判断类型: null -> false    类型不同 -> false
  • 判断值是否相同: 不同 -> false
@Override
public int hashCode() {
    int result = 17;
    result = 31 * result + x;
    result = 31 * result + y;
    result = 31 * result + z;
    return result;
}
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    ObjectMain that = (ObjectMain) o;
    if (x != that.x) return false;
    if (y != that.y) return false;
    return z == that.z;
}
复制代码


toString()

默认返回 ToStringExample@4554617c 这种形式,其中 @ 后面的数值为散列码的无符号十六进制表示

static {
  Log.info("1".toString());
}
复制代码


clone

不推荐使用 clone方法来实现对象的拷贝, 建议使用拷贝构造函数或者工厂模式

  • 浅拷贝:  引用的同一个对象
  • 深拷贝: 引用的对象不同
public static void main(String[] args) {
    // 拷贝的实现
    CloneExample a = new CloneExample();
    CloneExample b = new CloneExample(a);
    a.set("c");
    Log.info(b.get()); // a 说明是两个不同的对象
}
class CloneExample {
    private String a;
    CloneExample() {
        this.a = "a";
    }
    CloneExample(CloneExample e) {
        this.a = e.a;
    }
    public void set(String n) {
        this.a = n;
    }
    public String get() {
        return this.a;
    }
}
复制代码


抽象类

  • 不能实例化 只能继承
  • 如果一个类中存在抽象方法那么 这个类必须是抽象类, 定义抽象方法不要实现
abstract class Cat {
    public abstract void getName();
}
class Animal extends Cat {
    // 必须实现方法
    @Override
    public void getName() {
    }
}
复制代码


异常类 Exception

Error:

  • 虚拟机报错 VirtualMachineError
  • StackOverFlowError
  • OutOfMemoryError
  • AWTError

Exception:

  • IOException
  • EOFException
  • ...

RuntimeException


异常捕获

java中使用 try catch 捕获异常, finally 用于程序恢复

public static int main() {
    int a = 0;
    try {
        a = 1;
        throw new Exception("报错了");
        // 在没有异常的情况下 ,返回值等于 try内部的返回值
        // return a;
    } catch (Exception e) {
        Log.info(e.getMessage());
        a = 2;
        return a;
    } finally {
        a = 3;
        Log.info("final");
    //    return a;
    }
    //return a;
}


相关文章
|
28天前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第17天】本文详细介绍了Java编程中Map的使用,涵盖Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的并发处理和性能优化技巧,适合初学者和进阶者学习。
40 3
|
7天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
12天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
18天前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
57 5
|
16天前
|
安全 Java 调度
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
29 1
|
22天前
|
Java 数据处理 开发者
Java多线程编程的艺术:从入门到精通####
【10月更文挑战第21天】 本文将深入探讨Java多线程编程的核心概念,通过生动实例和实用技巧,引导读者从基础认知迈向高效并发编程的殿堂。我们将一起揭开线程管理的神秘面纱,掌握同步机制的精髓,并学习如何在实际项目中灵活运用这些知识,以提升应用性能与响应速度。 ####
43 3
|
24天前
|
Java
Java中的多线程编程:从入门到精通
本文将带你深入了解Java中的多线程编程。我们将从基础概念开始,逐步深入探讨线程的创建、启动、同步和通信等关键知识点。通过阅读本文,你将能够掌握Java多线程编程的基本技能,为进一步学习和应用打下坚实的基础。
|
25天前
|
存储 安全 Java
从入门到精通:Java Map全攻略,一篇文章就够了!
【10月更文挑战第19天】本文介绍了Java编程中重要的数据结构——Map,通过问答形式讲解了Map的基本概念、创建、访问与修改、遍历方法、常用实现类(如HashMap、TreeMap、LinkedHashMap)及其特点,以及Map在多线程环境下的使用和性能优化技巧,适合初学者和进阶者学习。
42 4
|
25天前
|
Java
[Java]Socket套接字(网络编程入门)
本文介绍了基于Java Socket实现的一对一和多对多聊天模式。一对一模式通过Server和Client类实现简单的消息收发;多对多模式则通过Server类维护客户端集合,并使用多线程实现实时消息广播。文章旨在帮助读者理解Socket的基本原理和应用。
20 1
|
25天前
|
SQL IDE Java
入门Cloud Toolkit:简化你的Java应用开发与部署流程
【10月更文挑战第19天】作为一名长期从事Java开发的程序员,我一直致力于寻找能够简化日常开发工作的工具。在众多工具中,阿里巴巴推出的Cloud Toolkit引起了我的注意。这款免费的插件旨在帮助开发者更轻松地进行开发、测试及部署工作,尤其是在与云服务交互时表现尤为出色。本文将从个人的角度出发,介绍Cloud Toolkit的基本功能及其使用技巧,希望能帮助初学者快速上手这款实用工具。
19 1