成员变量和局部变量的区别:
成员变量:类中方法外
堆内存中
随着对象的创建存在
随着对象的消失而消失
有默认初始化值
局部变量:方法定义中或者方法声明上
栈内存中
随着方法的调用而存在
随着方法调用完毕而消失
没有默认初始化值,必须定义赋值,然后才能使用(error:可能未初始化变量)
【注意:局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则】
形式参数是类名的时候如何调用:
上节课中我们提到,基本类型中,形式参数的改变不影响实际参数,引用类型中要影响。
引用类型包括类、接口和数组。
在上面这个demo中,studentdemo创建了method方法,这个方法的形参是student类型的,形参名是s。
下面我们在main方法中调用这个studentdemo类。
如果你看到了一个方法的形式参数是一个类(引用类型),这里需要的其实是该类的对象。
匿名对象:
没有名字的对象。
【对象的的确确被创建了,但是它没有名字,我们也不知道它的成员变量和方法名在堆内存中的地址。】
匿名对象的应用场景:
1. 仅仅只调用一次类中的方法的时候,调用方法。【newStudent().show();】
这种情况下,匿名对象 调用完毕就是垃圾,马上就可以被回收了。如果我只要这么一个方法,那么我就拿出来用一下,就可以扔了。也就是我们俗话说的【捞一笔就跑】。
2. 匿名对象可以作为参数传递。比如作为参数传给上面的方法。
多个匿名对象联动,一个调用一次方法,一个作为参数传递。
【看懂即可,一般我们不会主动用这个玩意】
封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式。
被private修饰的成员只能在本类中访问,不能在对象/其他类访问。
比如说一个student类中,我把成员变量age设为private,设一个public方法set_age来设置age,这样在对象中我就只能通过方法来设置age。
封装隐藏了实现细节(不给你访问),提供公共的访问方式,提高了代码的复用性和安全性。
【就像笔记本电脑的后盖】
private关键字:权限修饰符,修饰成员变量和成员方法。被其修饰的成员只能在本类中被访问。只有自己所在的类(中的方法)可以访问自己。对象都不行。
private标准应用格式:把成员变量用private修饰,提供对应的getXxx和setXxx用法。
this关键字的概述和应用:
如果成员变量和局部变量重名了,会发生什么事?我们之前说过,变量的使用规则是就近原则,如果重名了,就好像是把自己赋给自己,赋值这个过程无法进行。
所以,需要对name进行限定。
限定的方法:对成员变量用this关键字限定。
为了实现在set和get方法中也能见名知意,我们要求采用同样的命名,也就是要求要用this这个关键字。
this是当前类的对象的引用。
谁调用这个方法,this就代表谁!
【不过注意,如果没有和成员变量重名的局部变量,在方法中调用成员变量是不需要用this的。就算是按照就近原则,最近的也是成员变量】
构造方法:
回忆创建对象的格式:
Student s = new Student()
没有括号的叫变量,有括号的叫方法。
所以,Student()这就是个方法。也就是,我写Student()时,我实际上时调用了一个方法。
这就是Student类中的构造方法。在我写出这一句时,这个方法被调用了。
构造方法:给对象的数据进行初始化
格式:
方法名与类名相同;没有返回值,连void值都没有;没有具体的返回值
构造方法的注意事项:
1. 如果我们没有给出构造方法,系统将自动提供一个无参构造方法。
2. 如果我们给出了构造方法,系统将不再提供。
3. 构造方法可以带参数,也就是我们调用类时,把参数写在括号里。
4. 构造方法可以重载,规则和之前相同,方法名相同,形式参数不同。
因此,给成员变量赋值有两种方式:set方法和构造方法
建议永远自己给出无参构造方法。
重新给出类的组成:成员变量/成员方法/构造方法
创建对象做了哪些事情:
图解在内存中的存储方式:
下面有一段非常精彩的关于“什么时候定义成员变量”的课,但是太长了,直接复制讲义过来了。
/*
定义一个类Demo,其中定义一个求两个数据和的方法,
定义一个测试了Test,进行测试。
变量什么时候定义为成员变量:
如果这个变量是用来描述这个类的信息的,那么,该变量就应该定义为成员变量。
变量到底定义在哪里好呢?
变量的范围是越小越好。因为能及时的被回收。
*/
//方式1
/*
class Demo {
public int sum() {
int a = 10;
int b = 20;
int c = a + b;
return c;
}
}
*/
//方式1满足了我们的要求,但是不好。
//因为参与操作的数据现在是固定的。
//方式2
/*
class Demo {
public int sum(int a,int b) {
return a + b;
}
}
*/
//方式2可以满足我们的要求,但是呢我们学习过来面向对象的思想。
//我就再想,a,b可不可以定义为成员变量呢?
//如果可以,我们再改进一版
class Demo {
int a;
int b;
public int sum() {
return a + b;
}
}
//虽然这种方式可以,并且好像是符合了面向对象的思想。
//但是不好。
//因为我们曾经说过:类是一组相关的属性和行为的集合。
//并且类是通过事物转换过来的
//而类中的成员变量就是事物的属性
//属性是用来描述事物的
//同理:成员变量其实是用来描述类的。
//测试类
class Test {
public static void main(String[] args) {
//创建对象
//方式1测试
/*
Demo d = new Demo();
System.out.println(d.sum());
*/
//方式2测试
/*
Demo d = new Demo();
int a = 10;
int b = 20;
System.out.println(d.sum(a,b));
*/
//方式3测试
Demo d = new Demo();
d.a = 10;
d.b = 20;
System.out.println(d.sum());
}
}
static关键字:
当多个对象有共同的成员变量值时,java就提供了一个关键字来修饰:static
当一个类中的成员变量被定义为static时,所有该类的对象共享同一个值。
特点:
1. 随着类的加载而加载。(比如跟着Demo类一起出现的main方法)
2. 优先于对象存在。(对象在new的时候才出现)
3. 被类的所有对象共享。(例子:所有人共用饮水机,但是不能共用水杯)
5. 可以通过类名调用。其实它本身也可以通过对象名调用。(反正都是一样的)
【为什么main方法是静态的?因为它是被虚拟机调用的。毕竟main方法所在的类,没有对象】
推荐使用类名调用。
静态修饰的内容我们一般称其为:与类相关的类成员。
内存的分配方法:方法区中专门有一个静态区,加载方法的时候同时加载进来。
内存图解:
static关键字注意事项:
这一块也很精彩,直接复制讲义了
对于第一点,没有this关键字的意思,其实是不能访问非静态的成员变量。
所以第二点和第二点是一样的。
/*
static关键字注意事项
A:在静态方法中是没有this关键字的
如何理解呢?
静态是随着类的加载而加载,this是随着对象的创建而存在。
静态比对象先存在。
B:静态方法只能访问静态的成员变量和静态的成员方法
静态方法:
成员变量:只能访问静态变量
成员方法:只能访问静态成员方法
非静态方法:
成员变量:可以是静态的,也可以是非静态的
成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
简单记:
静态只能访问静态。
*/
class Teacher{
public int num = 10;
public static int num2 = 20;
public void show() {
System.out.println(num); //隐含的告诉你访问的是成员变量
System.out.println(this.num); //明确的告诉你访问的是成员变量
System.out.println(num2);
//function();
//function2();
}
public static void method() {
//无法从静态上下文中引用非静态变量 num
//System.out.println(num);
System.out.println(num2);
//无法从静态上下文中引用非静态方法 function()
//function();
function2();
}
public void function() {
}
public static void function2() {
}
}
classTeacherDemo {
public static void main(String[] args) {
//创建对象
Teacher t = new Teacher();
t.show();
System.out.println("------------");
t.method();
}
}
为什么main方法是静态的:
public static void main(String[] args){…}
public:访问权限最大(因为要被jvm调用)
static:可以通过类名来调用,不需要创建对象
void:没有返回值(返回给jvm没有意义)
main:约定的程序开始的地方
String[] args:这是一个字符串数组。事实上,它是一个确实存在的、长度为零的、啥也没有的数组。
【事实上,这个东西早期是为了接收键盘录入的数据的。这个用法已经废弃了,成为了一种约定俗成的习惯。】