赞
踩
在本章开始 前: 先思考一下 :
什么是面向对象?
看名字它是注重对象的。当解决一个问题的时候,面向对象会把事物抽象成对象的概念,就是说这个问题里面有哪些对象,然后给对象
赋一些属性和方法,然后让每个对象去执行自己的方法,问题得到解决。
换一个说法: 面向对象注重的是对象,也就是参与过程所涉及到的主体。是通过逻辑将一个个功能实现连接起来
补充:
Java是一门纯面向对象的语言(Object Oriented Program,继承OOP),在面向
对象的世界里,一切皆为对象。面向对象是解决问题的一种思想,主要依靠象
之间的交互完成一件事情。用面向对象的思想来涉及程序,更符合人们对事物
的认知,对于大型程序的设计、扩展以及维护都非常友好
下面再来一个问题:
什么是面向 过程?
从名字可以看出它是注重过程的。当解决一个问题的时候,面向过程会把事情拆分成: 一个个函数和数据(用于方法的参数) 。然后按照一定的顺序,执行
完这些方法(每个方法看作一个过程),等方法执行完了,事情就搞定了。
换一个说法: 面向过程注重的是过程,在整个过程中所涉及的行为,就是功能。
这里 : C语言就是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
下面我们通过 例子来 区分一下啥是 面下对象,啥是 面向过程。
这里 就来 举一个例子 :
洗衣机里面放有脏衣服,怎么洗干净?
面向过程的解决方法:
1、执行加洗衣粉方法;
2、执行加水方法;
3、执行洗衣服方法;
4、执行清洗方法;
5、 执行烘干方法;
以上就是将解决这个问题的过程拆成一个个方法(是没有对象去调用的),通过一个个方法的执行来解决问题。
面向对象的解决方法:
1、我先弄出两个对象:“洗衣机”对象和“人”对象
2、针对对象“洗衣机”加入一些属性和方法:“洗衣服方法”“清洗方法”、“烘干方法”
3、针对对象“人”加入属性和方法:“加洗衣粉方法”、“加水方法”
4、然后执行
人.加洗衣粉
人.加水
洗衣机.洗衣服
洗衣机.清洗
洗衣机.烘干
解决同一个问题 ,面向对象编程就是先抽象出对象,然后用对象执行方法的方式解决问题。
例子二 : 打麻将例子 你 我 他
面向过程: 打麻将 (你,我,他)
---------解决问题 拆成一个动作,把数据丢进去
面向对象: 我.打麻将(你,他) or 你.打麻将(我,他) or 他.打麻将(我,你)
---------解决问题 抽象出对象,对象执行动作 。
注意:面向过程和面相对象并不是一门语言,而是解决问题的方法,没有那个好坏之分,都有其专门的应用场景。
知道了 面向 对象, 那么 对象 从哪里来 ?
比如 上面 的 洗衣服 过程, 洗衣机, 人 这两个 对象 从哪里来呢?
其实 在 java 中 对象 是 从 类 中 创建出来的。
类就是一类对象的统称。对象就是这一类具体化的一个实例
那么下面我们就来 学习一下 类 .
简单的例子:我们做月饼的模子就是一个类,而通过这个模子可以做出月饼,那么在这个例子当中,类就是那个模 子,而月饼就是那个对象,所以月饼就是一个实
体。一个模子可以实例化无数个对象。 总的来说:类相当于一个模板,对象是由模板产生的样本。一个类,可以产生无数的对象。 声明一个类就是创建一个新的
数据类型,而类在 Java 中属于引用类型, Java 使用关键字 class 来声明类。我们来 看以下简单的声明一个类。
语法:
// 创建类
class ClassName{
field; // 字段(属性) 或者 成员变量
method; // 行为 或者 成员方法
}
这里:
class
为定义类的关键字,ClassName
为类的名字,{}
中为类的主体。
类中包含的内容称为类的成员。属性主要是用来描述类的,称之为类的成属性或者类成员变量。
方法主要说明类具有哪些功能,称为类的成员方法。
class Person{
public String name;
public int age;
}
来看这里 我们 就通过 class 创建 了 一个 类 ,注意: 类名 一般采用大驼峰。
这里 name / age可以 称为 字段 也可以称为 属性 ,还可以 称为 成员变量 (普通成员变量)。
(在类 中 成员变量 有两种 :1.普通成员变量 如 上面 2. 被 s’tatic定义静态成员变量 )
Person 是 人 的 意思,这里我们 定义的 name 和 age 正好 就是我们 每个人 拥有的 属性。
同样 我们定义的 类中 是 可以 添加 方法的 。
class Person {
public String name;
public int age;
public void eat() {
System.out.println(name + "大口吃饭");
}
public void sleep() {
System.out.println(name + "正在睡觉");
}
}
下面我们 就来 练习 一下 : 创建 类 ,以我们更好的掌握
注意: 这里 静态 方法 还没 讲到 可以 先 不 完成。
class Dog {
//这里 名字 和 颜色 就是 我们 的 成员变量
public String name; // 名字
public String color; // 颜色
// 狗的行为 (方法)
public void barks() {
System.out.println(name + "汪汪叫");
}
public void wag() {
System.out.println(name + "摇尾巴");
}
}
小练习完成后我们 来实例化我们的 对象。
之前我们 学习 过 new 他的 作用 就是用来帮我们 实例化对象的也可以说创建 一个 对象。
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 狗的行为 (方法) public void barks() { System.out.println(name + "汪汪叫"); } public void wag() { System.out.println(name + "摇尾巴"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); } }
这里我们 就 实例 化出 了 一个 dog 对象。当然 我们 也是
可以 实例化多个对象的(有了 模具 , 想要多少个 我们就能
new 多少个,这里要啥 女朋友 有 这么简单就好了)。
下面继续 :
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 狗的行为 (方法) public void barks() { System.out.println(name + "汪汪叫"); } public void wag() { System.out.println(name + "摇尾巴"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); Dog dog2 = new Dog(); Dog dog3 = new Dog(); Dog dog4 = new Dog(); Dog dog5 = new Dog(); } }
对象 有了 ,我们就 需要 通过 对象 去访问 类中的成员变量,这里我们就可以 通过 .
点号 来 访问我们的 成员变量。
语法: 引用(由类定义的变量名). 成员变量名。
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 狗的行为 (方法) public void barks() { System.out.println(name + "汪汪叫"); } public void wag() { System.out.println(name + "摇尾巴"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); dog.name = "旺财"; dog.color = "粉色"; dog.barks(); dog.wag(); } }
这里我们 就 成功访问 了 类中的 成员变量
如果 这里我们 没有赋值 呢 ?
这里就 将 dog.name
和 dog.color
给注释掉 来 看一下
可以看到 为 变为了 null, 这里 如果我们没有 给成员变量 赋值,这里 系统就会 赋于 默认值。
来看 这张图 : 这里 就是我们 每个 类型的默认值。
下面 继续 :
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 狗的行为 (方法) public void barks() { System.out.println(name + "汪汪叫"); } public void wag() { System.out.println(name + "摇尾巴"); } } public class Main { public static void main(String[] args) { Dog dog1 = new Dog(); Dog dog2 = new Dog(); } }
这里我们 创建 两个 引用 dog1 和 dog2 来 保存我们 对象的 地址。如:
刚刚 提到 过 被 static 修饰的变量 为 静态 成员变量,这里 就来 具体 展示 一下。
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 静态成员变量 public static int age; // 狗的行为 (方法) public void barks() { System.out.println(name + "汪汪叫"); } public void wag() { System.out.println(name + "摇尾巴"); } }
这里 就 通过 static 修饰 了 age 这里的 age 就是 静态 成员变量
1.通过 对象 :
但 这种 写法 编译器 会报 警告 , 一般 不建议 这样 写 。
2.通过类名 :
静态 成员变量 能够 通过 类名 来 调用 成员属性,那么我们 的 普通成员变量能不能 呢?
通过我们的 尝试 发现 他 是 不可以调用 的 ,这里 是为什么呢 ??
这里 就与 之前 提过 一嘴的 方法 区 有关 。
这里 我们的 静态成员 变量 是 属于类的 ,不是 属于 对象的 ,通过 对象 虽然 可以 访问到 静态成员变量, 但 编译器 会 包 警告 ,这里 我们 就需要通过 方法二 来调用 我们的 静态 成员 变量 。
下面我们 来 做一道 题 来 更 深刻的 理解 一下 静态 成员变量 。
public class HasStatic {// 1
private static int x = 100;// 2
public static void main(String args[]) {// 3
HasStatic hsl = new HasStatic();// 4
hsl.x++;// 5
HasStatic hs2 = new HasStatic();// 6
hs2.x++;// 7
hsl = new HasStatic();// 8
hsl.x++;// 9
HasStatic.x--;// 10
System.out.println(" x=" + x);// 11
}
}
想一想 这里 的 最终 输出 多少 ,
静态 成员 变量 你 会了 ,那么 静态成员 方法 也是 同理:
这里只 举例 类名 . 方法名
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 静态成员变量 public static int age; // 狗的行为 (方法) public void barks() { System.out.println(name + "汪汪叫"); } public void wag() { System.out.println(name + "摇尾巴"); } public static void Jump(){ System.out.println("正在跳"); } } public class Main { public static void main(String[] args) { Dog.age = 10; System.out.println(Dog.age); Dog.Jump(); } }
下面 就来 看 一下 这道题 :
package NowCoder;
class Test {
public static void hello() {
System.out.println("hello");
}
}
public class MyApplication {
public static void main(String[] args) {
// TODO Auto-generated method stub
Test test=null;
test.hello();
}
}
这里 能不能 将 heelo 打印 出来 呢 ?
答案: 这里 是 可以将 hello 打印 出来的 , 还记的我们 静态成员变量 是 放在方法 区 的 吗 ,这里 static 修饰的 是 方法 其实也 是 一样 的 , 同样是 放在 方法区的。
hello方法是一个静态方法,调用静态方法不需要创建实例对象。
此时的 Test test=null; 表示test这个引用不指向任何对象。所以此处可以正常访问。
但是我们需要牢记,静态方法的正确访问方式应该是用过类型来访问。即:Test.hello();
另外 : 在 静态成员变量中 我们 需要 注意一些 事项
如:
这里还是 拿 Dog 这个 类 举例 ,我们 创建 一个 fun方法 ,在 fun方法 中 创建 一个 静态 成员 变量 size.
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 静态成员变量 public static int age; // 狗的行为 (方法) public void barks() { System.out.println(name + "汪汪叫"); } public void wag() { System.out.println(name + "摇尾巴"); } public static void Jump(){ System.out.println("正在跳"); } //注意: public void fun(){ public static int size = 10; } } public class Main { }
可以 发现 这里报错 了, 其实 很容易 理解 。
1.被static 修饰的是属于类的,这样定义就不是属于类属于方法了
2.假设能定义 fun方法的调用需要 对象的引用来调用 如果可以定义static 的变量, 这个变量不需要对象 通过类名 Person 就可以调用
那么 我们 在 一个 静态 的方法中 定义 一个 静态的 变量 呢?
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 静态成员变量 public static int age; public static void Jump(){ System.out.println("正在跳"); } public static void func(){ public static int size = 10; } }
这里 虽然 不需要 对象 了 但是 被static 修饰的是属于类的,这样定义就不是属于类属于方法了
这里 不能 在 方法 中 创建 静态成员变量,那么我们 调用 方法 总可以了 吧 ,下面我们 就来 看一下 。
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 静态成员变量 public static int age; // 狗的行为 (方法) public static void func(){ System.out.println("测试 的 静态 方法"); } public void func2(){ func(); } }
可以看到 我们 在 普通 成员 方法 中 调用 静态 成员方法 编译器 没有 报错 , 其实 也 不难 想 。
普通方法需要对象,静态方法不需要对象 ,方法两部分不干扰,所以可以调用 如果在静态方法中调用普通呢?
如: 旅游 , 有对象的(普通成员 方法) 是不是 都会带 自己 的 女朋友 去, 如果 自己 一个人 偷偷 去 ,回来 不得 被 女朋友 提 分手 ,而 一个 单身狗(静态成员方法)是不是 可以 带 人 (有好感的 妹子 ) 去 , 或者 一个 人去 这 都 是 可以 的 。
同理 这 里 普通 成员 方法 都能 调用静态 方法 , 那么 在 静态方法 中 调用 静态 方法 同样 也是 可以的 。
普通 方法 能够 调用 静态方法, 那么 我们 静态 方法 能不能 调用 一个 普通方法 呢 ???
class Dog { //这里 名字 和 颜色 就是 我们 的 成员变量 public String name; // 名字 public String color; // 颜色 // 静态成员变量 public static int age; public static void func1(){ func2(); System.out.println("func1 :: 测试"); } public void func2(){ System.out.println("func2 :: 测试"); } }
可以 发现 这里 报错 了 , 为什么 呢?
想一想 其实非常简单, 我们知道静态方法是不需要对象的,而普通方法是需要对象 将一个需要对象的 放进一个没有对象的那肯定会发生错误的。
举例: 还是 拿 旅游 举例 , 一个 没有 对象的 人 叫 一个 有对象的 人 去 旅游 , 但是 有一个 条件 不能 带女朋友 , (我 自己 都没
有,不能让你带来 让我吃 狗粮 ) 如果 这个 人 去 了 那么 旅游 回来 ,女朋友百分之 百 会 提出 分手 (旅游 都 不带我 ,你肯定 是 不 爱
我 ),这时 肯定是 不能 去 的 吗 (相比 一个人 旅游 还不如 和 女朋友 在一起 )。
那么 这 不就 一个 道理,在 没有 对象的 方法 中 调用 需要对象的 方法 拿肯定是 不行 的 。
如果非要 在 静态 方法中 调用 不同 方法 其实 也 非常简单 , 这里 还是 旅游 举例 , 这里 就 直接 拉上 对象 不就 可以 了 吗 。
代码 这样写 :
静态 方法 中 没有对象我们创建 一个 对象 来 使用。
这里 普通 成员变量 和 静态 成员 变量 就 讲完了 ,下面 来 画个 图 形象的 体现 一下 两者之间的关系。
这里 补充 :
在 类中 定义的变量 是可以 被 fine 修饰 的
class Student{
public final int SIZE = 10;
public static final int SIZE2 = 20;
}
final修饰的叫常量,也属于对象。 被final 修饰,后续不可更改 同样 final 也是 可以修饰 静态变量为静态的常量,属于类本身,只有一份 被final修饰,后续不可更该 另外一个变量存放在哪里和你是否被fine修改无关
注意: 常量 一般 使用 大写
看完 静态 成员 变量下面我们 来学习一下 构造方法 ,
通过前面知识点的学习知道,在Java方法内部定义一个局部变量时,必须要初始化,否则会编译失败
public static void main(String[] args) {
int a;
System.out.println(a);
}
// Error:(26, 28) java: 可能尚未初始化变量a
要让上述代码通过编译,非常简单,只需在正式使用a之前,给a设置一个初始值即可。如果是对象:
那么 如何 初始 化对象 呢 ?
class Dog {
public String name;
public int age;
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "旺财";
dog.age = 10;
}
可以看到 我们 这里 成员 变量 就 2 个 初始 化 直接 通过 dog.
即可 ,如果 成员 变量 一多 是不是 就 不太方便 ,那么 对象 要如何初始化呢?
这里 在 来 一个问题 : 局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?
怀着 这 两个 问题 来 看一下我们的 构造方法。
构造方法
概念:构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
另外 : 在对对象产生(对象实例化/ new 的执行 过程 ) 会有两个 步骤 。
1.为对象分配内存空间
2.调用合适的构造方法 (一个 类 中可以 拥有 多个 构造方法 ,如: 不带 参数 带 参数 (这个 参数 又会 有 个数 区别) 这里 就 构成 了 重载)
当 这 2 个 步骤 走完 才会真正的 创建 对象。
下面 就来 演示 一下 :
class Dog { public String name; public int age; public Dog(){ System.out.println("不带参数的 构造方法"); } public Dog(String name){ this.name = name; System.out.println("带有 一个 参数的构造 方法"); } public Dog(String name, int age){ this.name = name; this.age = age; System.out.println("带有 两个 参数的 构造 方法"); } } public class Main { public static void main(String[] args) { Dog dog1 = new Dog(); Dog dog2 = new Dog("旺财"); Dog dog3 = new Dog("小黑", 14); } }
可以看到我们 就 创建 出 3 个 构造 方法 。 这里 的 构造 方法 也 是 可以 被 private
修饰 的 , 此时 其他 的 类 就无法 通过 new 这个 构成方法 来 创建 对象。
另外 : 当然 构造方法 所处类的内部是可以被调用的,因为 private 就是 将 所修饰部分 私有化,只有内部才能使用。外者不能使用既然 构造方法 可以私有化,肯定由它的作用: 实现 单例模式 的 大前提,现在不讲,还不会
这里 大家 会不会 有一个 疑问 ? 为啥 一开始 没写 构造 方法 不是 一样 创建 出对象 。
其实 如果 我们没有写 构造 方法 ,我们的 编译器 会 默认 创建 一个 不带 参数的 构造 方法。
class Dog { public String name; public int age; // public Dog() { // System.out.println("不带参数的 构造方法"); // } // // public Dog(String name) { // this.name = name; // System.out.println("带有 一个 参数的构造 方法"); // } // // public Dog(String name, int age) { // this.name = name; // this.age = age; // System.out.println("带有 两个 参数的 构造 方法"); // } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); } }
这里 就 先 将 我们 创建 的 构造 方法 屏蔽 掉 我们 执行 下 看看 。
这里 就 是 成功 执行 了 程序 。
注意 : 如果我们 在类中 写 了 构造 方法 ,编译器 就不会 会默认 提供 不带参数的 构造 方法了。
还是 这个 代码 : 我们 将 不带 参数 的 构造 方法 注释 掉
class Dog { public String name; public int age; // public Dog() { // System.out.println("不带参数的 构造方法"); // } public Dog(String name) { this.name = name; System.out.println("带有 一个 参数的构造 方法"); } public Dog(String name, int age) { this.name = name; this.age = age; System.out.println("带有 两个 参数的 构造 方法"); } }
可以 看到 报错 了 。
另外 : 构造方法支持重载. 规则和普通方法的重载一致 构造方法重载规则:类名相同,参数的类型和个数,两者中,至少有一个不同项。调用构造方法时,编译器会自动筛选调用合适的构造方法
构成方法 了解 完我们 来 了解 一下 this
关于 this 我们 有 三种 用法 ,这里 就先 罗列 出来
1.this.data 调用当前的对象的 属性/字段/成员变量
2.this.func() 调用当前的对象的方法
3.this()调用当前对象的其他构造方法
1.this.data 调用当前的对象的 属性/字段/成员变量
这个 this.data 是 用来 解决 形参名不小心与成员变量名相同的 问题 。
先来 看一下 同名 不适用 this 的 情况
class Dog { public String name; public int age; public Dog() { System.out.println("不带参数的 构造方法"); } public Dog(String name) { this.name = name; System.out.println("带有 一个 参数的构造 方法"); } public Dog(String name, int age) { name = name; age = age; System.out.println("带有 两个 参数的 构造 方法"); } public void sleep() { System.out.println(age + "岁的 小狗"); System.out.println(name + "正在睡觉"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog("小黑",4); dog.sleep(); } }
这里就 通过带有 两个 参数 的 构造 方法 ,对 age 和 那么 赋值 ,然后 条用 sleep() 方法 ,来 看 赋值情况
这里 看到 我们 的 age 为 0 ,name 为 null , 这里 是 为什么呢 ???
其实 这里 有点 与 c 中 的 局部 变量 优先 一样 ,
这里 传入 的 形参 名 age 和 name 与 赋值 的 名字 相同 , 编译器 ,并不知情 ,会按照 局部变量 优先 , 此时 就会出现 自己 赋值 给 自己 的 情况
,
这里 就可以 使用 我们 的 this 来 指定 当前变量是 这个 类中 的 。
public Dog(String name, int age) {
this.name = name;
this.age = age;
System.out.println("带有 两个 参数的 构造 方法");
}
public void sleep() {
System.out.println(age + "岁的 小狗");
System.out.println(name + "正在睡觉");
}
第一种用法 看完 我们 来 看 第二种
2.this.func() 调用当前的对象的方法
class Dog { public String name; public int age; public void eat() { System.out.println(name + "开心的 吃"); } public void sleep(String name) { this.name = name; this.eat(); System.out.println(name + "正在睡觉"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); dog.sleep("小黑"); } }
这里 就 通过`` this.方法名 ` 调用 了 eat 方法 。
3.this()调用当前对象的其他构造方法
注意: 这里 this() , 括号 内 是 可以带参数的 参数 类型 与 参数个数决定 所调用 的 构造方法,另外 这里 this() 只能使用在 构造方法 当中 ,而且 只能 在 第一行 。
下面 演示 :
class Dog { public String name; public int age; public Dog() { // 调用 带有 两个 参数 的 构造 方法 this("小黑", 15); System.out.println("不带参数的 构造方法"); } public Dog(String name) { // 调用 不带参数的 构造 方法 this(); this.name = name; System.out.println("带有 一个 参数的构造 方法"); } public Dog(String name, int age) { this.name = name; this.age = age; System.out.println("带有 两个 参数的 构造 方法"); } public void sleep() { System.out.println(age + "岁的 小狗"); System.out.println(name + "正在睡觉"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); } }
另外 :
这样 使用 this.()
是 不可以的 , 进入 不带参数 的 构造方法 , 然后 通过``this.(“小黑”) 进入 带有一个 参数的 构造方法 , 然后 又 通过
this.()`
绕回 来 了 ,这里 就会 死循环 , 显然 是 不可以的 ,这里我们的编译器 ,就 比较 智能 直接报错 了 。
下面 就 进入 到 本文 的 最后一讲 代码 块 。
概念:
使用 {} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下四种:
普通代码块(本地代码块)
构造块(实例代码块)
静态块 (静态代码块)
同步代码块(后续讲解多线程部分再谈)
这里主要 讲 实例代码块 和 静态 代码 块
public class Main {
public static void main(String[] args) {
{ //直接使用{}定义,普通方法块
int x = 10;
System.out.println("x1 = " + x);
}
int x = 100;
System.out.println("x2 = " + x);
}
}
执行结果 为 10 和 100.
这种 代码块 用 的比较少 ,下面 就来 看我们的 实例 代码块
构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。
class Dog { public String name; public int age; // 这里 就是 实例 代码块 { name = "小黑"; age = 20; } public void eat() { System.out.println(name + "大口的吃"); } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); dog.eat(); } }
这里 就通过 实例代码 块 初始化 了 实例 成员变量 。
使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。
class Dog { // 姓名 public String name; // 年龄 public int age; // 颜色 public static String color; // 性格 public static String character; 实例代码 块 { this.name = "小黑"; this.age = 20; } 静态 代码 块 static { color = "粉色"; character = "乖巧"; } public void eat() { System.out.println(name + "大口的吃"); } public void fun(){ System.out.println(name + " 真是 " + character + "的 狗 "+ "颜色 是" + color); } } public class Main { public static void main(String[] args) { Dog dog = new Dog(); dog.eat(); dog.fun(); } }
最终 我们的 结果 :
最后我们 来 看一下 实例 代码 块 和 静态 代码 块 的 区别
下面 就来 看代码 分析 :
class Dog { private String name; public int age; public void func(){ System.out.println("这是 测试 方法"); } { System.out.println("小灰灰"); } static { System.out.println("红 太郎 "); } static { System.out.println("灰太狼"); } } public class Main{ public static void main(String[] args) { Dog dog = new Dog(); dog.func(); } }
想一想 这里 我们 会 输出 什么:
可以看到 我们 会先 输出 静态 代码 块里的 内容 然后 是 实例代码 块 ,最后 是 我们的 方法 。
通过 上面我们 能 总结 出 一种 规律 (这里 只 给出 了 一组 测试 用例 , 如果 你 多尝试 几次 也 是 这样 的 )
结论: 当 一个类 中 既有 静态 代码块 和 实例 代码块,和 方法时 ,会先调用 静态 代码块 ,然后是 实例 代码 块 ,最后是 方法
class Dog { private String name; public int age; public void func(){ System.out.println("这是 测试 方法"); } { System.out.println("小灰灰"); } static { System.out.println("红 太郎 "); } static { System.out.println("灰太狼"); } } public class Main{ public static void main(String[] args) { Dog dog = new Dog(); // dog.func(); } }
这里我们 讲 调用 的 方法 注释 掉 , 来看一下 结果 。
可以看到 还是 我们的 静态 代码块 先 执行 ,然后 是 实例 ,这里 没有 通过 对象 调用 fun 方法 ,所以 fun 没有 生效。
另外 : 静态 代码 块只能 执行 一次
class Dog { private String name; public int age; public void func(){ System.out.println("这是 测试 方法"); } { System.out.println("小灰灰"); } static { System.out.println("红 太郎 "); } static { System.out.println("灰太狼"); } } public class Main{ public static void main(String[] args) { Dog dog = new Dog(); dog.func(); Dog dog2 =new Dog(); } }
来 看 我们 再 new 了 一个 对象 时 , 这里 静态代码 块 中 的 红太郎 和 灰太狼 就 没有 了 。
总结 :
静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的。
静态代码块执行完毕后, 实例代码块(构造块)执行,再然后是构造函数执行
最后 我们 再来 思考 一个 问题 静态 代码块 ,和 静态 成员 变量 是那个 先执行 呢 ??
下面 我们 就 来 通过 代码 来看 一下 。
class Dog { private String name; public int age; public static int count = 10; count public void func(){ System.out.println("这是 测试 方法"); } { System.out.println("小灰灰"); } static { count = 20; System.out.println("红 太郎 "); } static { System.out.println("灰太狼"); } } public class Main{ public static void main(String[] args) { System.out.println(Dog.count); } }
想一下 这里的 count 输出 多少 。
这里 我们 直接 通过 类名 调用 count 发现 count 等于 10 ,可以 发现 这里 是 先 执行 了 public static int count = 10;再执行 了 静态 代码块中 的
count = 20;
那么我们 调换 一下 位置 再来看一下 。
class Dog { private String name; public int age; public void func(){ System.out.println("这是 测试 方法"); } { System.out.println("小灰灰"); } static { count = 20; System.out.println("红 太郎 "); } static { System.out.println("灰太狼"); } public static int count = 10; } public class Main{ public static void main(String[] args) { System.out.println(Dog.count); } }
此时 count 又等于 多少 呢??
可以发现 等于 10 这里 是 先 执行 了 代码 块 ,再执行 了 public static int count = 10;
那么 这里 可以得出 结论 , 静态代码 块 与 静态 成员变量的 执行 顺序 与 写 的 顺序 有关 ,谁在前面 谁 先 执行 ,注意 这里 静态代码 块 之间 这时 这样的 。
最后 来 看 一道题目 : 请问 下面 cut 等于几 ??
public class Test{
static int cnt = 6;
static{
cnt += 9;
}
public static void main(String[] args){
System.out.println("cnt = " + cnt);
}
static{
cnt /=3;
};
}
按照上面总结 的 我们 很容易得出答案 , 如 先 执行 cnt = 6, 然后 再 执行 cnt += 9 最后 再执行 cnt /= 3; 答案 就为 5。
你写 对 了吗??
本文就 到 此为止。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。