函数:
封装一段具体实现功能的代码;
类:
封装了同一类事物的共有的属性(成员变量)和行为(函数);
封装可以提高代码复用性,降低开发和维护的难度;
可以隐藏事物的细节,提高安全性、易用性和美观性;还可以提高代码的复用性;
##4.2 权限修饰符
private
表示被修饰的成员(成员变量、函数)是私有的,只能在定义它的类中使用,不能被其他地方使用;注意:不能修饰类(外部类)
public
protected
基类的 protected
成员是包内可见的,并且对子类可见;
若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected
方法,而不能访问基类实例的protected
方法。
package p2;
class MyObject2 {
protected Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
package p22;
public class Test2 extends MyObject2 {
public static void main(String args[]) {
MyObject2 obj = new MyObject2();
obj.clone(); // Compile Error ----(1)
Test2 tobj = new Test2();
tobj.clone(); // Complie OK ----(2)
}
}
对于(1)而言,clone()方法来自于类MyObject2本身,因此其可见性为包p2及MyObject2的子类,虽然Test2是MyObject2的子类,但在Test2中不能访问基类MyObject2的protected方法clone(),因此编译不通过;对于(2)而言,由于在Test2中访问的是其本身实例的从基类MyObject2继承来的的clone(),因此编译通过。
注意:不能修饰类(外部类)
default
(即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
封装,就是包装,主要用来隐藏事物的实现细节,提高程序的安全性;如果外界需要访问被封装的属性,需要对外提供公开的getter和setter函数用public
构造函数,又叫做构造器,就是在对象创建的时候由JVM自动调用的函数,创建对象都需要调用构造函数
作用:
格式:
1.修饰符
2.方法名:与类同名
3.形参列表
4.方法体 为属性/成员变量赋值
格式:
1 2(3){
4
}
举例
/*
构造函数的定义和使用:
存在的意义,创建对象的过程中为属性赋值;
让属性赋值的时机提前了
*/
class Student{
//属性
String name;
int age;
/*
定义两个参数的构造方法
*/
public Student(String n,int a){
name = n;
age = a;
}
//方法
public void getInfo(){
System.out.println("姓名:" + name + ",年龄:" + age);
}
}
class TestStudent
{
public static void main(String[] args)
{
//创建学生对象
//Student s = new Student();
//调用两个参数的构造方法创建Student对象,并且在创建对象的过程中为name、age属性赋值
Student s = new Student("李雷",20);
//以下操作属性属于后天给值
/*
s.name = "韩梅梅";
s.age = 19;
*/
s.getInfo();
}
}
注意事项
一个类中,如果不显式的定义构造方法,编译器默认提供无参构造方法;
一旦定义了构造方法,编译器将不再提供默认无参构造
构造方法可以重载
class Animal
{
String brand;
int age;
public Animal(String b,int a){
brand = b;
age = a;
}
public Animal(){
}
}
class TestAnimal
{
public static void main(String[] args)
{
//创建动物对象(使用两个参数的构造)
Animal a = new Animal("狗",3);
//创建动物对象(使用空参数的构造)
Animal a1 = new Animal();
}
}
this
:表示对自身所属对象的引用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zHSUckDa-1656645884732)(./assets/015-this%25E5%2585%25B3%25E9%2594%25AE%25E5%25AD%2597.png)]
作用:
记录当前正在创建或者使用的对象的内存地址
/*
this的第一个作用:
记录当前正在创建或者使用的对象的内存地址
*/
class Student
{
//属性
String name;
int age;
public Student(String n,int a){
name = n;
age = a;
System.out.println("我是Student类中的构造方法..this=" + this);
}
//打印信息
public void info(){
System.out.println(name + "-->" + age);
System.out.println("我是Student类中的info方法..this=" + this);
}
}
class TestStudent
{
public static void main(String[] args)
{
//创建Student类的对象
Student s = new Student("李雷",20);
System.out.println(s);
s.info();
}
}
区分成员变量和局部变量
/*
this的第二个作用:
区分成员变量和局部变量
*/
class Person
{
private String name;
private int age;
private char gender; //性别
//构造方法(三个参数)
public Person(String name,int age,char gender){
this.name = name;
this.age = age;
this.gender = gender;
}
//getter&setter
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
//打印信息
public void info(){
System.out.println(name + "-->" + age + "-->" +gender);
}
}
class TestPerson
{
public static void main(String[] args)
{
//创建对象
Person p = new Person("韩梅梅",19,'女');
p.info();
}
}
构造方法之间相互调用
【注意事项】:
this
进行调用(构造方法可以重载)构造方法
可以调用构造方法
构造方法
可以调用一般方法
一般方法
不可以调用构造方法
一般方
法可以调用一般方法
class Teacher
{
String name;
int age;
String address; //籍贯
//构造方法(3个)
public Teacher(String name,int age,String address){
this(name,age);
//this.name = name;
//this.age = age;
this.address = address;
System.out.println("我是Teacher类中三个参数的构造..this=" + this); //④
}
//构造方法(2个)
public Teacher(String name,int age){
//this.name = name;
/*
调用一个参数的构造,让其完成对name属性的赋值操作
错误: 找不到符号
原因:以下的调用方式属于一般方法的调用,不适合构造方法
Teacher(name);
*/
this(name);
this.age = age;
/*
错误: 对this的调用必须是构造器中的第一个语句
理解:构造函数的调用必须是在首行
this(name);
*/
System.out.println("我是Teacher类中两个参数的构造..this=" + this); //③
}
//构造方法(1个)
public Teacher(String name){
//调用本类重载的空参构造
this();
this.name = name;
System.out.println("我是Teacher类中一个参数的构造..this=" + this); //②
}
//构造方法(空参)
public Teacher(){
/*
错误: 递归构造器调用
构造方法之间相互调用不能形成回路
this("闫校",40,"山西");
*/
/*
尝试在构造方法中调用一般方法
可以
*/
show();
System.out.println("我是Teacher类中空参数的构造..this=" + this); //①
}
public void show(){
System.out.println("我是一般方法show..");
}
public void func(){
/*
尝试在一般方法中调用构造方法
不可以
*/
//this();
System.out.println("我是一般方法func..");
}
}
class TestTeacher
{
public static void main(String[] args)
{
//创建对象(匿名对象)
new Teacher("老郭",20,"上海");
}
}
static关键字修饰属性称为:静态属性、类属性
核心:与类有关,与对象无关
如果某个属性的值是固定的,将其定义为static修饰;所有对象公用;节省内存
格式:直接将static关键字写在成员变量的数据类型前面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NNOhMtCz-1656645884734)(./assets/wps1.jpg)]
使用方法:静态成员变量和类的对象无关,直接通过类名调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C5oTL3ZC-1656645884735)(./assets/wps2.jpg)]
特点:一个类中的静态成员变量,在这个类的所有对象中共享
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-crMlOE3C-1656645884736)(./assets/wps3.jpg)]
静态成员变量和非静态成员变量的区别:
静态成员变量 | 非静态成员变量 | |
---|---|---|
保存位置 | 方法区的静态区域 | 堆内存的对象空间中 |
书写格式 | 需要使用static关键字修饰,将static关键字直接写在数据类型前面 | 不需要使用static关键字修饰 |
生命周期 | 类加载的时候就分配空间和赋值;直到这个类被卸载(或者整个程序结束) | 创建对象的时候才分配空间和赋值;对象成为垃圾空间被回收的时候 |
使用 | 可以直接通过类名使用,和类的对象无关 | 必须通过类的对象使用 |
修改后的影响范围 | 所有对象都影响 | 只对这一个对象有影响 |
概念:static修饰的函数
格式:
public static void main(String args){
System.out.println("this is a static method!");
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qVtxlBHP-1656645884736)(./assets/wps4.jpg)]
使用方法:静态函数和类的对象无关,直接通过类名调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YuV5lwDl-1656645884737)(./assets/wps5.jpg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GJJqwixn-1656645884738)(./assets/wps6.jpg)]
内存原理:
java程序的内存划分:
寄存器;本地方法区;方法区;栈内存;堆内存;
方法区:主要保存静态成员、class、常量等一些东西;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d7wbhfun-1656645884738)(./assets/wps7.jpg)]
注意事项
静态函数不能调用非静态函数和非静态成员变量
原因:
非静态函数和非静态成员变量必须依赖类的对象使用;
而静态函数使用不需要对象,所以在静态函数中不能直接调用非静态函数和非静态成员变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmQcEavq-1656645884739)(./assets/wps8.jpg)]
非静态函数可以调用静态函数
原因:
非静态函数只能通过类的对象使用;如果可以调用非静态函数,说明此时已经存在对象;已经存在对象,说明类已经加载完毕;类已经加载完毕,所以静态函数肯定可以使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Av7StV4h-1656645884740)(./assets/wps9.jpg)]
构造函数不能是静态的
因为构造函数是在创建对象的时候用来给对象的成员变量赋值用的;如果构造函数是静态的,不需要对象就能使用,没有意义
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b4mbOAB7-1656645884740)(./assets/wps10.jpg)]
静态函数中不能使用和对象有关的关键字
例如this
,就是表示一个对象的引用的,而静态函数是没有对象就可以直接使用的,所以不能在静态函数里面使用this
等关键字;
还有一个关键字:super
static的注意事项:
首先要理解类和对象在内存中的生命周期现象(早、晚问题)
类加载要远远早于对象加载 --> 类现有、对象后有
通过以上的观点,得到:
代码块,就是使用大括号括起来的一段代码;
书写格式:
class Test{
{
代码;
}
}
作用:随着类的加载,一并加载到内存中,并且只加载一次
好处:将某些依赖对象/容器的创建时机提前
格式:
class test{
static{
//定义的代码
}
}
注意:一般在开发中,静态代码块都要写在类的下面
作用:
因为在类加载完成时,静态代码块已经执行结束,某些需要提前完成的工作,可以放在静态代码块中执行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8vNcYM5H-1656645884741)(./assets/wps12.jpg)]
存在于类中,方法体外的局部代码块
作用:将多个构造函数中相同的代码抽取到构造代码块中,在创建对象的过程中,构造代码块随着每个对象的创建都会执行一次
优点:增强代码复用性
格式:
class test{
{
//定义代码
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fg2XR4Bl-1656645884742)(./assets/wps13.jpg)]
作用:用来限制变量的使用范围
格式:
class test{
public void func(){
{
//定义代码
}
}
}
补充:虽然格式和构造代码块一模一样,但是构造代码块存在于类的成员位置;而局部代码块存在于方法体中;