——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
一、成员变量和局部变量的区别
1. 在类中的位置不同:
成员变量:类中方法外
局部变量:方法定义或方法声明上
2. 在内存中的位置不同:
成员变量:在堆内存中
局部变量:在栈内存中
3. 生命周期不同:
成员变量:随着对象的创建而存在,随对象的消失而消失
局部变量:随方法体的调用而存在,随方法调用完毕而消失
4. 初始化值不同:
成员变量:有默认初始化值
局部变量:没有默认值,在使用之前必须显示初始化,赋值后才能使用
二、Java中参数的传递问题
Java中方法的参数可以有两种类型:
基本数据类型:byte, short, int, long ,float, double, char, boolean
引用数据类型:某个类的变量,基本类型数组
1.当方法被调用时,如果传入方法的实际参数是基本数据类型,那么如果在方法体中对参数进行修改,将不会影响实际参数的值,因此基本数据类型的参数传递方式是值传递。
2.当方法被调用时,传入方法的实际参数是某一个类的变量,或基本类型数组的变量时,此时实际传入方法的是该类对象或数组在内存中的地址值,当在方法体内对该地址进行操作时,实际上操作的是地址所指向的对象,因此会使对象发生改变,但这种传递方式仍然属于值传递,因为传递的是地址的值。
注:Java中参数传递的方式为值传递
Java参数传递示例代码:
参数为基本类型变量
下面的代码通过一个方法实现两个整数互换值的操作
public class ParapassDemo {
public static void main(String[] args) {
int a = 10;
int b = 29;
System.out.println("交换前: a = " + a + ",b = " + b);
swap(a, b);
System.out.println("交换后: a = " + a + ",b = " + b);
}
public static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
}
输出结果:
交换前: a = 10,b = 29
交换后: a = 10,b = 29
很可惜从结果上看,该程序并没有完成预期的目的,交换前后,实际参数a,b的值没有交换,下面用一张图来解释为什么出现这种结果。
从上图可以看出,方法中交换的仅仅是局部变量a,b的值,而实际参数在main()方法中一直没有改变,因为调用方法时仅仅将实参的值传递给了swap()方法。
参数为引用类型
public class ParamPassDemo {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person();
System.out.println("交换前: p1 = " + p1 + ",p2 = " + p2);
swap(p1, p2);
System.out.println("交换后: p1 = " + p1 + ",p2 = " + p2);
}
public static void swap(Person p1, Person p2) {
Person temp = p1;
p1 = p2;
p2 = temp;
}
}
/* * 定义一个Person类 */
class Person {
}
输出结果:
交换前: p1 = blogcode.Person@1e58cb8,p2 = blogcode.Person@179935d
交换后: p1 = blogcode.Person@1e58cb8,p2 = blogcode.Person@179935d
从输出结果看到,和基本类型类似,p1和p2所指向的对象没有变化,变化的只是局部变量中临时的p1和p2的引用
请看下面这张图解:
三、匿名对象
所谓的匿名对象,从字面上理解就是没有命名的对象,实际意义其实也是如此,匿名对象就是没有指定变量名称,只能使用一次的对象。
例如:
new Person();
new Cat();
new String();
……
应用场景:
1. 调用某个对象的方法,且该对象仅仅使用这一次
2. 作为实际参数,直接传递给某个方法的形参。
四、封装
1.概念:隐藏类的属性和实现细节,对外提供公共的访问方式。
要较好的理解封装的概念,需要先了解Java提供的访问权限修饰符。
以下三个关键字在Java中用于为类和类中的成员设定访问权限:
2.Java提供访问控制权限主要有两个原因:
1.让类的使用者无法触及他们不该触及的部分,这些部分是类在内部操作数据所必须的,但不应该暴露给用户使用,也就是隐藏实现细节
2.当类的设计者改变类的内部实现方式时,不用担心会影响到使用该类的用户,例如当你以一种简单的方式实现了某一个类,但之后你发现这种简单的实现方式效率并不高,这时你可以放心的改变这个类的内部实现,而不需要担心会影响用户正常使用该类。
由此也得出了封装的优点:
A.隐藏实现细节,提供公共访问方式
B.提高代码复用性
C.提高代码的安全性
3.封装的典型应用示例
需求:定义一个Person类,将成员变量私有,并提供公共的访问方式。
代码:
public class Person {
//私有的成员变量
private String name;
private int age;
//公共的访问方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
4.this关键字
this关键字代表当前类的对象的引用
通俗的理解:哪个对象调用该方法,那么该方法内部的this关键字就代表那个对象
应用场景:解决局部变量和成员变量同名问题
五、构造方法
1.作用:用于给对象中的成员变量进行初始化操作
2.定义格式:
public Person(){}
3.注意事项:
4.一个标准的自定义类案例:
/* * 一个标准的学生类 */
public class Student {
/* * 私有的成员变量: * 姓名: String name * 年龄: int age */
private String name;
private int age;
/* * 一个空参构造方法 */
Student() {
}
/* * 一个带参数构造方法,用于初始化成员变量 */
Student(String name, int age) {
this.name = name;
this.age = age;
}
/* * 与成员变量相对应的setXxx()/getXxx()方法 * 用于获取和修改成员变量 */
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
学生类的测试类:
/* * 学生类的测试类 */
public class StudentDemo {
/* * 主方法:用于创建学生类对象,调用学生类对象的方法 */
public static void main(String[] args) {
//创建学生类对象
//空参构造创建对象
Student student1 = new Student();
//通过带参构造创建对象,并初始化成员变量
Student student2 = new Student("小明", 18);
//调用setXxx()方法设置成员变量
student1.setName("小红");
student1.setAge(17);
//调用getXxx()方法获取成员变量
String name1 = student1.getName();
int age1 = student1.getAge();
String name2 = student2.getName();
int age2 = student2.getAge();
//输出获取的成员变量
System.out.println("student1:" + name1 + "," + age1);
System.out.println("student2:" + name2 + "," + age2);
}
}
测试结果:
student1:小红,17
student2:小明,18
六、理解创建对象的过程
代码:Student s = new Student();
做了哪些事情?
1. 把Student.class文件加载到内存中
2. 在栈内存为变量s开辟空间
3. 在堆内存为学生对象开辟空间
4. 对学生对象的成员变量进行默认初始化 (name = null, age = 0)
5. 对学生对象的成员变量进行显示初始化
6. 通过构造方法给成员变量进行初始化
7. 对象构造并初始化完毕,把对象的地址赋值给变量s
以上的初始化步骤由JVM完成,理解对象的创建过程有助于对Java程序执行流程的掌握,并且在遇到错误的时候能够快速找到问题所在。
七、static关键字
static 代表静态的意思,用于修饰成员变量和成员方法。
1.静态的特点:
一个示例代码说明静态的特点:
class Student {
//非静态变量
int num = 10;
//静态变量
static int num2 = 20;
//静态方法
public static void method(){
System.out.println("这是一个静态方法");
}
}
class StudentDemo {
public static void main(String[] args) {
//创建学生类对象
Student s = new Student();
//通过对象名调用非静态成员变量
System.out.println("对象名调用非静态成员变量num : " + s.num);
//因为优先于对象存在,所以可以通过类名来调用
System.out.println("类名调用静态成员变量num2 : " + Student.num2);
//也可以通过对象名调用静态成员变量,但不提倡这么做
System.out.println("对象名调用静态成员变量num2 : " + s.num2);
//通过类名调用静态方法
Student.method();
}
}
2.静态的注意事项:
-在静态方法中只能访问静态成员
-静态方法中不隐式包含this关键字:静态是随着类的加载而加载,this是随着对象的创建而存在。
示例代码:
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() {
}
}
class TeacherDemo {
public static void main(String[] args) {
//创建对象
Teacher t = new Teacher();
t.show();
System.out.println("------------");
t.method();
}
}
3.静态变量和成员变量的区别
-A:所属不同
静态变量:属于类,类变量
成员变量:属于对象,对象变量,实例变量
-B:内存位置不同
静态变量:方法区的静态区
成员变量:堆内存
-C:生命周期不同
静态变量:静态变量是随着类的加载而加载,随着类的消失而消失
成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失
-D:调用不同
静态变量:可以通过对象名调用,也可以通过类名调用
成员变量:只能通过对象名调用
八、Java中类的组成
类的组成: