成员变量
**成员变量和局部变量的定义与区别:**变量分为成员变量和局部变量,成员变量是在类范围内定义的变量,局部变量是在方法中定义的变量。
成员变量又分为实例属性和类属性
没有加上static修饰符的就是实例属性,代表该类的每个对象都用有此属性。
加上了static修饰符修饰的属性,则为类属性,属于类所有,整个项目中仅此一份,属于共享使用。
局部变量分为形参和方法局部变量。
下面举个例子:
public class Hero {
String name;//名字 实例属性
static String camp;//阵营 类属性
public static void main(String[] args) {
Hero h1 = new Hero();
h1.name = "剑圣";
Hero.camp = "近卫方";
Hero h2 = new Hero();
h2.name = "剑魔";
Hero.camp = "天灾方";
System.out.println(h1.name+""+h1.camp+"\n"+h2.name+""+h2.camp);
}
}
运行结果如下:
其中属性name,是实例属性,在这个类里面创建的所有对象都有这个属性,就像每个人都会有自己的名字一样,并且我改名不会对其他人产生任何影响,这就是实例属性
而改变加了static修饰符的camp属性,改变以后,不管输出多少次,camp的值都为天灾方,说明改变时,整个都会随之改变。说明类属性,属于类所有,整个项目中仅此一份,且共享使用。
注意,在访问类属性时可以直接通过类名访问,不需要再创建对象。
this关键字和方法调用
在类的定义中,通过this关键字可以访问到该类的实例属性,this其实就是一个指向当前类的对象地址的关键字,this关键字可以让类中的一个方法访问该类中的另一个方法或实例成员变量。
下面通过一个例子来体会一下this关键字的作用
public class Hero {
String name;
//创建一个方法,接收参数name
public void setName(String name) {
name = name; //给成员属性name赋值
}
public static void main(String[] args) {
Hero h = new Hero();
h.setName("剑魔");
System.out.println(h.name);
}
}
运行结果如图:
从这里可以看出,成员变量与局部变量同名,我们传了参数剑魔给name,运行结果却发现它的内容为空。
这里就是因为变量不明确导致的,两个变量名相同,这时我们就可以用this 来解决这个问题,代码如下:
public class Hero {
String name;
//创建一个方法,接收参数name
public void setName(String name) {
this.name = name; //给成员属性name赋值
}
public static void main(String[] args) {
Hero h = new Hero();
h.setName("剑魔");
System.out.println(h.name);
}
}
运行结果如图:
这时我们可以明显看到name不是为null了,关键字this指定了成员属性,我们传进去的参数能准确赋值给成员变量name。所以以后在给成员变量赋值时,为了避免参数名相同而导致输出结果为null,我们可以用关键字this来指定成员变量。这就是this关键字的作用。
关键字this还能在方法调用时起到作用,下面举一个例子
public class Hero{
public void test1() {
System.out.println("这是方法一");
}
public void test2() {
this.test1();
System.out.println("这是方法二");
}
}
通过关键字this 我们不用在方法里面创建对象以后再去调用其他方法,可以直接通过this关键字来访问。这就是this方法的调用。
注意,this是指定当前对象,不能与关键字static连用。
类的封装
类的成员封装:封装是面向对象的三大特征之一
封装的主要意思是:该隐藏的隐藏,该开放的开放,就像胶囊一样,可以看见胶囊,但是不能看见胶囊的材料和生产工序
封装实现目的:
- 隐藏类的实现细节
- 使用者可以通过实现预定的方法访问数据
- 可以对数据进行检查提高数据的可用性
- 便于修改,提高代码的可维护性
为什么要进行封装
public class Hero{
String name;
int age;
}
public class Test{
public static void main(String[] args) {
Hero h1 = new Hero();
h1.name = "1";
h1.age = -18;
System.out.println("英雄的姓名为:"+h1.name);
System.out.println("英雄的年龄为:"+h1.age);
}
}
运行结果如图:
这里面的年龄是负数,年龄不能为负数,这个问题就可以从封装来解决
在这个时候,年龄是没有进行封装的,我们可以随意改变年龄的值
下面对年龄来进行封装
我们可以在年龄前面加一个private,这个时候会发现在测试类里面不能给年龄赋值
static关键字的使用
static关键字是什么
static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。
静态成员变量
static修饰成员变量 :如果有数据需要被共享给所有对象使用时,那么就可以使用static修饰。
class Student{
String name;
//使用了static修饰country,那么这时候country就是一个共享的数据。
static String country = "中国"; //国籍
//构造函数
public Student(String name){
this.name = name;
}
}
class Demo9 {
public static void main(String[] args)
{
Student s1 = new Student("张三");
Student s2 = new Student("陈七");
s1.country = "小日本";
System.out.println("姓名:"+s1.name+" 国籍:"+ s1.country); // 小日本
System.out.println("姓名:"+s2.name+" 国籍:"+ s2.country); // 小日本
}
}
静态的成员变量与非静态的成员变量的区别:
- 作用上的区别:
- 静态的成员变量的作用共享一个 数据给所有的对象使用。
- 非 静态的成员变量的作用是描述一类事物的公共属性。
- 数量与存储位置上的区别:
- 静态成员变量是存储方法 区内存中,而且只会存在一份数据。
- 非静态的成员变量是存储在堆内存中,有n个对象就有n份数据。
- 生命周期的区别:
- 静态的成员变量数据是随着类的加载而存在,随着类文件的消失而消失。
2.非静态的成员数据是随着对象的创建而存在,随着 对象被垃圾回收器回收而消失。
静态代码块
静态代码块(想在main方法之前执行,可以给静态成员变量赋值)
静态代码块:定义成员位置,使用static修饰代码块()位置:类方法外执行:随着类的加载而执行且执行一次,优先于main方法构造和构造方法执行
public class StaticDemo02 {
public static void main(String[] args) { CodeBlock2.z = 100; CodeBlock2 cb = new CodeBlock2(); CodeBlock2 cb2 = new CodeBlock2(1, 2); }}class CodeBlock2 { int x; int y; static int z;
{// System.out.println("CodeBlock 构造代码块"); print(); } public CodeBlock2() {// print(); System.out.println("我是无参构造方法"); }
static {
System.out.println("我是静态代码块"); z = 100; } public CodeBlock2(int x, int y) {// print(); this.x = x; this.y = y; System.out.println("我是带参构造方法"); } public void print() { System.out.format("(%d,%d)%n", x, y); } public void method() { int num = 10; // 局部代码块 { int a = 20; System.out.println(num); System.out.println(a); } int a = 30; // 同步代码块 synchronized(new Object()){ } }}我是静态代码块(0,0)我是无参构造方法(0,0)我是带参构造方法
静态方法
使用static关键字修饰一个方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法