java基础语法
一个java程序可以认为是一系列对象的集合,而对这些对象通过调用彼此的方法来协同工作
对象:对象是类的一个实例,有状态和行为,比如,一条狗是一个对象,他的状态:颜色。名字,品种等,行为有:摇尾巴,叫等
类:类是一个模版,他描述一类对象的行为和状态
方法:方法就是行为,一个类可以有很多方法,逻辑运算,数据修改以及所有动作都是在方法中完成的
实例变量:每一个对象都有独特的实例变量,对象的状态由这个实例变量的值决定
HelloWord
public class HelloWorld {
/* 第一个Java程序
* 它将输出字符串 Hello World
*/
public static void main(String[] args) {
System.out.println("Hello World"); // 输出 Hello World
}
}
基本语法
大小写敏感
类名:对于所有类来说,类名的首字母应该大写,如果类名由若干个单词组成,那么每个单词的首字母应该大写
方法名:所有的方法名都应该以小写字母开头,如果方法名含有若干个单词,则后面的每个单词首字母大写
源文件名:源文件名必须和类名相同,当保存文件的时候,应该使用类名作为文件名保存,文件名后缀为.java
主方法入口:所有的java程序由`public static void main(String[] args)方法开始执行
java标识符
java所有的组成部分都需要名字,类名,变量名以及方法名都被称为标识符
关于标识符:
所有标识符都应该以字母,$
或者_
开始
首字符之后可以是字母,$
,_
或数字的任意字符组合
关键字不能用作标识符
标识符大小写敏感
java修饰符
java可以使用修饰符来修饰类中方法和属性,主要有两类修饰符:
访问控制修饰符:default,public,protected,private
非访问控制修饰符:final,abstract,static,synchronized
java变量
局部变量
类变量(静态变量)
成员变量(非静态变量)
java数组
数组是储存在堆上的对象,可以保存多个同类型变量
java枚举
class FreshJuice {
enum FreshJuiceSize{ SMALL, MEDIUM , LARGE }
FreshJuiceSize size;
}
public class FreshJuiceTest {
public static void main(String[] args){
FreshJuice juice = new FreshJuice();
juice.size = FreshJuice.FreshJuiceSize.MEDIUM ;
}
}
枚举可以单独声明或者声明在类里面。方法、变量、构造函数也可以在枚举中定义
java关键字
下面列出了 Java 关键字。这些保留字不能用于常量、变量、和任何标识符的名称
基本类型
关键字 | 含义 |
---|---|
boolean | 布尔型 |
byte | 字节型 |
char | 字符型 |
double | 双精度浮点 |
float | 单精度浮点 |
int | 整型 |
long | 长整型 |
short | 短整型 |
变量引用
关键字 | 含义 |
---|---|
super | 父类、超类 |
this | 本类 |
void | 无返回值 |
保留关键字
关键字 | 含义 |
---|---|
goto | 是关键字,但不能使用 |
const | 是关键字,但不能使用 |
类与对象相关
关键字 | 中文含义 |
---|---|
class | 类 |
interface | 接口 |
extends | 继承(类) |
implements | 实现(接口) |
new | 创建新对象 |
package | 包 |
import | 导入 |
this | 当前对象 |
super | 父类 |
abstract | 抽象 |
控制流程
关键字 | 中文含义 |
---|---|
if | 如果 |
else | 否则 |
switch | 多分支选择 |
case | 分支条件 |
default | 默认 |
while | 当……时循环 |
do | 先执行后判断 |
for | 循环 |
break | 跳出循环 |
continue | 继续下一次循环 |
return | 返回 |
异常与断言
关键字 | 中文含义 |
---|---|
try | 尝试执行 |
catch | 捕获异常 |
finally | 最终执行 |
throw | 抛出异常 |
throws | 声明抛出异常 |
assert | 断言 |
其他关键字
关键字 | 中文含义 |
---|---|
static | 静态的 |
final | 最终的/不可修改的 |
abstract | 抽象的 |
synchronized | 同步的 |
native | 本地方法(C/C++) |
transient | 瞬时的(不序列化) |
volatile | 易变的(线程共享) |
strictfp | 精确浮点 |
instanceof | 实例判断 |
java注释
单行注释://
多行注释:以/*
开始,以*/
结束
文档注释:文档注释以 /** 开始,以 */ 结束,通常出现在类、方法、字段等的声明前面,用于生成代码文档,这种注释可以被工具提取并生成 API 文档
public class HelloWorld {
/* 这是第一个Java程序
* 它将输出 Hello World
* 这是一个多行注释的示例
*/
public static void main(String[] args){
// 这是单行注释的示例
/* 这个也是单行注释的示例 */
System.out.println("Hello World");
}
}
继承
在java中,一个类可以由其他类派生,如果你创建一个类,而且已经存在一个类具有你所需要的属性和方法,那么你可以将创新的类继承该类
利用继承的方法,可以重用已经存在类的方法和属性,而且不用重写代码,被继承的类成为超类,派生类称为子类
接口
在java中,接口可理解为对象间相互通信的协议,接口在继承中扮演很重要的角色
接口只定义派生要用到的方法,但是方法的具体实现完全取决于派生类
源文件与编译型运行的区别
java类与对象
作为一个面向对象的编程语言
类:
定义对象的蓝图,包括属性和方法
public class Sun {...}
对象:
类的实例,具有状态和行为
Sun Sunsun = new Sun
继承:
一个类可以继承另一个类的属性和方法
public class Sun extends Empty {...}
封装:
将对象的状态(字段)私有化,通过公共方法访问
private String name;
public String getName() { return name ; }
多态:
对象可以表现为多种形态,主要通过方法重载和方法重写实现
- 方法重载:
public int add(int a, int b) { ... }
和public double add(double a, double b) { ... }
- 方法重写:
class Animal {
public void makeSound() {}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow");
}
}
抽象:
使用抽象类和接口来定义必须实现的方法,不提供具体实现
- 抽象类:
public abstract class Shape { abstract void draw(); }
- 接口:
public interface Animal { void eat(); }
抽象大概就是指只关心做什么,而不关心怎么做
通俗一点说:
- 你在调用
.draw()
、.eat()
方法时,并不需要知道它怎么实现的; - 你只关心“画图”、“吃东西”这件事本身;
- 实际的“怎么画”、“怎么吃”留给具体类(子类)去实现。
抽象类不能直接实例化,可以有抽象方法和普通方法,子类必须实现抽象方法,除非子类也是抽象类
接口:
定义类必须实现的方法,支持多重继承
public interface Animal {
void eat(); // 接口中的方法默认就是抽象的(Java 8 以前)
}
- 接口中定义的方法默认是
public abstract
- 接口用于定义一个规范、能力或功能
- 类通过
implements
实现接口,必须实现方法
用于“定义行为”,比如“能吃”、“能跑”、“能飞”这种抽象能力
方法:
定义类的行为,包括在类中的函数
[修饰符] 返回类型 方法名([参数]) {
// 方法体:要执行的代码
}
public void displayInfo() {
System.out.println("Info");
}
方法重载:
同一个类中可以有多个同名的方法,但是参数不同
public class MathUtils {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
}
对象
对象是类的一个实例
类只是一个模版,可以描述一类对象的行为和状态
public class Dog {
String breed;
int size;
String colour;
int age;
void eat() {
}
void run() {
}
void sleep(){
}
void name(){
}
}
一个类可以包含一下类型变量
局部变量:在方法,构造方法或者语句块中定义的变量被称为局部变量,变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁
成员变量:成员变量是定义在类中,方法体之外的变量,这种变量在创建对象的时候实例化,成员变量可以被类中方法,构造方法和特定类的语句块访问
类变量:也声明在类中,方法体之外,但是必须少女革命为static类型
构造方法
每个类都有构造方法
在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法
public class Puppy{
public Puppy(){
}
public Puppy(String name){
// 这个构造器仅有一个参数:name
}
}
创建对象
对象是根据类创建的,在java中,使用关键字new来创建一个新的对象,创建对象需要三个步骤
声明:声明一个对象,包括对象名称和对象类型
实例化:使用关键字new来创建一个对象
初始化:使用new创建对象时,会调用构造方法初始化对象
public class Dog {
public Dog(String name){
System.out.println("小狗的名字是 : " + name );
}
public static void main(String[] name) {
Dog myDog = new Dog("siri");
}
}
访问实例变量的方法
通过已创建的对象来访问成员变量和成员方法
/* 实例化对象 */
Object referenceVariable = new Constructor();
/* 访问类中的变量 */
referenceVariable.variableName;
/* 访问类中的方法 */
referenceVariable.methodName();
使用Object类型声明变量只能在编译时访问访问Object类中的方法和属性,但在运行时,可以通过强制类型转换将其转换为特定类型,以便访问特定类型的方法和属性
通过对象访问类的变量和方法,以及Object 类型引用的限制和类型转换
Demo
// 父类
class Animal {
public void speak() {
System.out.println("动物发出声音");
}
}
// 子类
class Dog extends Animal {
public void bark() {
System.out.println("汪汪汪!");
}
}
// 主类
public class Demo {
public static void main(String[] args) {
// 使用 Object 保存 Dog 对象(向上转型)
Object obj = new Dog();
// 只能访问 Object 的方法
System.out.println("obj.toString() = " + obj.toString()); // ✅ 合法
// obj.bark(); // ❌ 编译错误:Object 类型没这个方法
// 正确做法:向下转型成 Dog 类型
if (obj instanceof Dog) { // 类型检查
Dog myDog = (Dog) obj; // 强制类型转换
myDog.speak(); // 继承的
myDog.bark(); // Dog 独有方法
}
}
}
/*obj.toString() = Dog@2f4d3709
动物发出声音
汪汪汪!*/
Dog husky = new Dog(); // 原本你是用 Dog 类型引用,可以访问 bark()
Object obj = new Dog(); // 你现在用 Object 保存它,就“看不到” bark() 了
// obj.bark(); 编译器会说:"我不知道 obj 是 Dog!"
Dog realDog = (Dog) obj; // 强制告诉编译器:别怕!它真的是 Dog!
realDog.bark(); // 成功访问 Dog 独有方法
所以这个就是向下转型
实例
举个例子
public class Puppy {
private int age;
private String name;
// 构造器
public Puppy(String name) {
this.name = name;
System.out.println("小狗的名字是 : " + name);
}
// 设置 age 的值
public void setAge(int age) {
this.age = age;
}
// 获取 age 的值
public int getAge() {
return age;
}
// 获取 name 的值
public String getName() {
return name;
}
// 主方法
public static void main(String[] args) {
// 创建对象
Puppy myPuppy = new Puppy("Salt_Fish");
// 通过方法来设定 age
myPuppy.setAge(19);
// 调用另一个方法获取 age
int age = myPuppy.getAge();
System.out.println("小狗的年龄为 : " + age);
// 也可以直接访问成员变量(通过 getter 方法)
System.out.println("变量值 : " + myPuppy.getAge());
}
}
小狗的名字是 : Salt_Fish
小狗的年龄为 : 19
变量值 : 19
源文件声明规则
学习源文件的声明规则,当在一个源文件中定义多个类,并且还有import语句和package语句时,要主要这些规则
- 一个源文件中只能有一个 public 类
- 一个源文件可以有多个非 public 类
- 源文件的名称应该和 public 类的类名保持一致。例如:源文件中 public 类的类名是 Employee,那么源文件应该命名为Employee.java
- 如果一个类定义在某个包中,那么 package 语句应该在源文件的首行
- 如果源文件包含 import 语句,那么应该放在 package 语句和类定义之间。如果没有 package 语句,那么 import 语句应该在源文件中最前面
- import 语句和 package 语句对源文件中定义的所有类都有效。在同一源文件中,不能给不同的类不同的包声明
java基本数据类型
变量就是申请内存来储值,当创建变量时,需要在内存中申请空间
Java 的两大数据类型:
- 内置数据类型
- 引用数据类型
Java语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型
public class PrimitiveTypeTest {
public static void main(String[] args) {
// byte
System.out.println("基本类型:byte 二进制位数:" + Byte.SIZE);
System.out.println("包装类:java.lang.Byte");
System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE);
System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE);
System.out.println();
// short
System.out.println("基本类型:short 二进制位数:" + Short.SIZE);
System.out.println("包装类:java.lang.Short");
System.out.println("最小值:Short.MIN_VALUE=" + Short.MIN_VALUE);
System.out.println("最大值:Short.MAX_VALUE=" + Short.MAX_VALUE);
System.out.println();
// int
System.out.println("基本类型:int 二进制位数:" + Integer.SIZE);
System.out.println("包装类:java.lang.Integer");
System.out.println("最小值:Integer.MIN_VALUE=" + Integer.MIN_VALUE);
System.out.println("最大值:Integer.MAX_VALUE=" + Integer.MAX_VALUE);
System.out.println();
// long
System.out.println("基本类型:long 二进制位数:" + Long.SIZE);
System.out.println("包装类:java.lang.Long");
System.out.println("最小值:Long.MIN_VALUE=" + Long.MIN_VALUE);
System.out.println("最大值:Long.MAX_VALUE=" + Long.MAX_VALUE);
System.out.println();
// float
System.out.println("基本类型:float 二进制位数:" + Float.SIZE);
System.out.println("包装类:java.lang.Float");
System.out.println("最小值:Float.MIN_VALUE=" + Float.MIN_VALUE);
System.out.println("最大值:Float.MAX_VALUE=" + Float.MAX_VALUE);
System.out.println();
// double
System.out.println("基本类型:double 二进制位数:" + Double.SIZE);
System.out.println("包装类:java.lang.Double");
System.out.println("最小值:Double.MIN_VALUE=" + Double.MIN_VALUE);
System.out.println("最大值:Double.MAX_VALUE=" + Double.MAX_VALUE);
System.out.println();
// char
System.out.println("基本类型:char 二进制位数:" + Character.SIZE);
System.out.println("包装类:java.lang.Character");
// 以数值形式而不是字符形式将Character.MIN_VALUE输出到控制台
System.out.println("最小值:Character.MIN_VALUE="
+ (int) Character.MIN_VALUE);
// 以数值形式而不是字符形式将Character.MAX_VALUE输出到控制台
System.out.println("最大值:Character.MAX_VALUE="
+ (int) Character.MAX_VALUE);
}
}
基本类型:byte 二进制位数:8
包装类:java.lang.Byte
最小值:Byte.MIN_VALUE=-128
最大值:Byte.MAX_VALUE=127
基本类型:short 二进制位数:16
包装类:java.lang.Short
最小值:Short.MIN_VALUE=-32768
最大值:Short.MAX_VALUE=32767
基本类型:int 二进制位数:32
包装类:java.lang.Integer
最小值:Integer.MIN_VALUE=-2147483648
最大值:Integer.MAX_VALUE=2147483647
基本类型:long 二进制位数:64
包装类:java.lang.Long
最小值:Long.MIN_VALUE=-9223372036854775808
最大值:Long.MAX_VALUE=9223372036854775807
基本类型:float 二进制位数:32
包装类:java.lang.Float
最小值:Float.MIN_VALUE=1.4E-45
最大值:Float.MAX_VALUE=3.4028235E38
基本类型:double 二进制位数:64
包装类:java.lang.Double
最小值:Double.MIN_VALUE=4.9E-324
最大值:Double.MAX_VALUE=1.7976931348623157E308
基本类型:char 二进制位数:16
包装类:java.lang.Character
最小值:Character.MIN_VALUE=0
最大值:Character.MAX_VALUE=65535
引用类型
在java中,引用类型指向一个对象,指向对象的变量是引用变量,这些变量在声明时被指定为一个特定的类型,比如 Employee、Puppy 等。变量一旦声明后,类型就不能被改变了
- 对象、数组都是引用数据类型
- 所有引用类型的默认值都是null
- 一个引用变量可以用来引用任何与之兼容的类型
java常量
常量在运行时无法修改
在java中使用final关键字来修饰常量,声明方式和变量类似
final double PI = 3.1415926;
虽然常量名也可以使用小写,但是为了便于区别使用大写字母表示常量
符号 | 字符含义 |
---|---|
\n | 换行 (0x0a) |
\r | 回车 (0x0d) |
\f | 换页符(0x0c) |
\b | 退格 (0x08) |
\0 | 空字符 (0x0) |
\s | 空格 (0x20) |
\t | 制表符 |
“ | 双引号 |
‘ | 单引号 |
\ | 反斜杠 |
\ddd | 八进制字符 (ddd) |
\uxxxx | 16进制Unicode字符 (xxxx) |
自动类型转换
整型,实型,字符型数据都可以混合运算,运算中,不同类型的数据先转化为同一类型,然后进行运算
转换从低级到高级
低 ------------------------------------> 高
byte,short,char—> int —> long—> float —> double
数据类型转换必须满足如下规则:
- 不能对boolean类型进行类型转换
- 不能把对象类型转换成不相关类的对象
- 在把容量大的类型转换为容量小的类型时必须使用强制类型转换
- 转换过程中可能导致溢出或损失精度,例如:
byte b = (byte)i;因为 byte 类型是 8 位,最大值为127,所以当 int 强制转换为 byte 类型时,值 128 时候就会导致溢出- 浮点数到整数的转换是通过舍弃小数得到,而不是四舍五入,例如:
(int)-45.89f == -45
强制类型转换
条件是转换的数据类型必须是兼容的
public class ForceTransform {
public static void main(String[] args){
int i1 = 123;
byte b = (byte)i1;//强制类型转换为byte
System.out.println("int强制类型转换为byte后的值等于"+b);
}
}
int强制类型转换为byte后的值等于123
隐含强制类型转换
- 1、 整数的默认类型是 int。
- 2、 小数默认是 double 类型浮点型,在定义 float 类型时必须在数字后面跟上 F 或者 f
java变量
变量:
即在内存中的一个存储区域,此区域有名称和类型
先声明后使用
java是强类型语言,每个变量在声明的时候必须声明数据类型
变量只能作用在作用域内
声明变量格式(记得要遵循声明的规则)
static int a;
修饰符+数据类型+变量名
基本格式
type identifier [ = value][, identifier [= value] ...] ;
type 数据类型
identifier 变量名
java支持的变量类型
局部变量:是在方法,构造函数或块内部声明的变量,他们在声明的方法,构造函数或块执行结束后销毁,局部变量在声明需要初始化,否则会出现编译错误
实例变量:实例变量是在类中声明,但是在方法,构造函数或块之外,他们属于类的实例,每个类的实例在不明确初始化时,实例变量会被赋予默认值
静态变量或类变量:类变量是在类中用static关键字声明的变量,他们不属于类而不是实例,所有该类的实例共享一个类变量的值,类变量在类加载时被初始化,而且只初始化一次
java重写与重载
重写(Override)是指子类定义了一个与其父类中具有相同名称、参数列表和返回类型的方法,并且子类方法的实现覆盖了父类方法的实现。 即外壳不变,核心重写!
重写的好处在于子类可以根据需要,定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法。这样,在使用子类对象调用该方法时,将执行子类中的方法而不是父类中的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,抛出 IOException 异常或者 IOException 的子类异常。
在面向对象原则里,重写意味着可以重写任何现有方法
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
}
}
但是这样写就会报错
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
public void bark(){
System.out.println("狗可以吠叫");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
b.bark();
}
}
因为animal里没有bark这个方法
要改成Dog b = new Dog()
就可以
方法的重写规则
- 参数列表与被重写方法的参数列表必须完全相同
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)
- 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected
- 父类的成员方法只能被它的子类重写
- 声明为 final 的方法不能被重写
- 声明为 static 的方法不能被重写,但是能够被再次声明
- 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
- 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法
- 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以
- 构造方法不能被重写
- 如果不能继承一个类,则不能重写该类的方法
super关键字
当要在子类中调用父类中被重写的方法是,需要使用super关键字
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
super.move(); // 应用super类的方法
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal b = new Dog(); // Dog 对象
b.move(); //执行 Dog类的方法
}
}
重载
是指在一个类中,方法名字相同,但是参数不同,返回类型可以相同也可以不同,一个重载的方法(或者构造函数)都必须是独一无二的参数类型列表
重载规则:
被重载的方法必须改变参数列表(参数个数或类型不一样);
被重载的方法可以改变返回类型;
被重载的方法可以改变访问修饰符;
被重载的方法可以声明新的或更广的检查异常;
方法能够在同一个类中或者在一个子类中被重载
无法以返回值类型作为重载函数的区分标准
public class Overloading {
public int test(){
System.out.println("test1");
return 1;
}
public void test(int a){
System.out.println("test2");
}
//以下两个参数类型顺序不同
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
public static void main(String[] args){
Overloading o = new Overloading();
System.out.println(o.test());
o.test(1);
System.out.println(o.test(1,"test3"));
System.out.println(o.test("test4",1));
}
}
重写与重载之间的区别
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
java多态
简单来说是同一个行为具有多个不同表现形式或形态的能力,就是同一个接口,使用不同的实例而执行不同的操作
多态存在的三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}