4.类的成员:
3.1.类的成员 -> 属性介绍(成员变量):
a.语法格式:
- 1.
修饰符 数据类型 属性名 = 初始化值 ;
- 2.说明1: 修饰符
- 常用的权限修饰符有:
private、缺省、protected、public
- 其他修饰符:
static、final
- 常用的权限修饰符有:
- 3.说明2:数据类型
- 任何基本数据类型(如int、Boolean) 或 任何引用数据类型。
- 4.说明3:属性名
- 属于标识符,符合命名规则和规范即可。
b.变量的分类:
- 1.成员变量和局部变量
- 在
方法体外类体内
声明的变量称为成员变量
- 在方法体
内部
声明的变量称为局部变量
- 在
- 2.成员变量和局部变量相同点:
- 都有生命周期,都有作用域
- 先声明,后使用
- 3.成员变量和局部变量差异点:
局部变量
除形参外,均需显式初始化局部变量
指的是定义在成员方法内
的变量,存储在栈
内,定义在方法内部,方法的形参
,代码块内
,构造器内部,构造器形参的变量
都叫做局部变量局部变量
:不能用权限修饰符修饰,可以用final修饰成员变量
:是在类中定义的属性
,存储在堆
中(暂时先忽略掉static类型的属性)成员变量
:在声明时候指明其权限,权限修饰符不一样成员变量
:权限修饰符有private,public,缺省,protected
成员变量
的类型可以是任意类型的,包含基本类型或者引用类型。成员变量如果不赋值,有默认值
,默认值规则和数组的一致。
- 4.默认初始化值情况
- 属性会根据其类型有初始化值;
局部变量没有初始化值,所以在使用局部变量之前一定要进行显示赋值
- 当一个对象被创建时,会对其中各种类型的
成员变量(属性)
自动进行初始化赋值。除了基本数据类型之外的变量类型都是引用类型
- 属性会根据其类型有初始化值;
成员变量(属性)
可以被本类,也可以被其他类使用;而局部变量只能在本类中对应的方法使用
比较项 1 | 成员变量 | 局部变量 |
---|---|---|
声明的位置 | 直接声明在类中 | 方法形参或内部、代码块内、构造器内等 |
修饰符 | private、public、static、final等 | 不能用权限修饰符修饰,可以用final修饰 |
初始化值 | 有默认初始化值 | 没有默认初始化值,必须显式赋值,方可使用 |
内存加载位置 | 堆空间 或 静态域内 | 栈空间 |
3.2.类的成员 ->行 为(方法)介绍:
a.方法特点:
- 1.
方法
是类或对象行为特征的抽象
,用来完成某个功能操作。在某些语言中 也称为函数或过程
- 2.将功能封装为方法的
目的是,可以实现代码重用,简化代
码 - 3.Java里的
方法不能独立存在
,所有的方法必须定义在类里
b.方法的声明格式:
- 1.
权限修饰符 返回值类型 方法名(参数类型 形参1, 参数类型 形参2, ….){// 方法体程序代码 ;return 返回值; }
- 权限修饰符:
public,缺省,private, protected
static、final、abstract
来修饰的方法,后面再讲- 返回值类型:
- 没有返回值:void。
- 有返回值,声明出返回值的类型。与方法体中“return 返回值”搭配使用
- 方法体:
- 里面写完成功能的具体语句,可以是输入,输出,变量,分支,循环,方法的调用等,但是方法体中的方法里面不可以再次定义方法。即
方法不可以嵌套定义
- 里面写完成功能的具体语句,可以是输入,输出,变量,分支,循环,方法的调用等,但是方法体中的方法里面不可以再次定义方法。即
方法名
:属于标识符,命名时遵循标识符命名规则和规范,“见名知意”形参列表
:- 可以包含零个,一个或多个参数。多个参数时,中间用“,”隔开
- 调用带参数的方法的时候,一定要对应着参数列表传入相同类型或者兼容类型的参数
- 实参和形参的类型,个数,顺序必须得一致
- .返回值:方法在执行完毕后返还给调用它的程序的数据
- 权限修饰符:
c.代码练习:
package com.jianqun.package01;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-01-31-23:15
*/
public class Object02 {
public static void main(String[] args) {
int [][] map = {{0,0,1},{0,0,2},{0,0,3}};
MyTools tools = new MyTools();
tools.printlnArr(map);
}
}
class MyTools{
public void printlnArr(int[][] map){
//遍历数组
for (int i = 0; i < map.length;i++){
for (int j = 0; j < map[i].length; j++){
System.out.println(map[i][j]);
}
}
}
}
d.方法执行的内存加载机制
d1.图像解析方法的加载机制
d2.成员方法使用中的注意事项:
- 1.
一个方法只有一个返回值
,如果需要返回多个值,则可以以数组形式返回
。
package com.jianqun.package01;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-01-31-23:15
*/
public class Object02 {
public static void main(String[] args) {
AA aa = new AA();
int[] sumAndSub = aa.getSumAndSub(1, 1);
System.out.println("****两数相加********" + sumAndSub[0] + "******两数相减********" + sumAndSub[1]);
}
}
class AA{
public int[] getSumAndSub(int n,int m){
int[] ints = new int[2];
ints[0] = n + m;
ints[1] = n - m;
return ints;
}
}
- 2.一个方法
可以有0个参数,也可以多个参数
- 3.
参数的类型可以是任意的
,包含基本类型或者引用类型 - 4.调用参数的时候,一定对着参数列表传入相同类型或者兼容类型的参数
e.成员方法的调用说明
e1.代码实现成员方法之间的调用
- 1.同一个类中的方法调用,可以直接调用
- 2.
跨类调用
方法,如A类调用B类中的方法
的话,就需要通过对象名调用
,如:对象名.方法名(参数)
;
package com.jianqun.package01;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-01-0:48
*/
public class Object03 {
public static void main(String[] args) {
Ao ao = new Ao();
ao.m1();
}
}
class Ao{
public void print(int n){
System.out.println("print方法被调用");
}
public void sayOk(){
print(10);
System.out.println("继续执行sayOk方法");
}
public void m1(){
//创建B类方法
Bo b = new Bo();
b.hi();
}
}
class Bo{
public void hi(){
System.out.println("B类的hi方法被调用");
}
}
f.方法传参机制:
f1.变量赋值:
f2.方法的形参传递机制:值传递
Java中方法的参数传递只有一种方式:值传递
,即讲实际参数值的副本传入方法内,而参数本身不受影响
f2-1.基本数据类型的传参
基本数据类型,传递的是值,形参的任何改变都不影响实参
f2-2.引用数据类型的传参机制
- 引用数据类型传递的是地址:
- 1.例题1:
- 1.例题2:
// 类名:Object04.java
package com.jianqun.package01;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-01-10:15
*/
public class Object04 {
public static void main(String[] args){
Bb b = new Bb();
int[] arr = {1,2,3};
//调用方法,传递数组参数
b.test1(arr);
System.out.println("主方法中循环输出");
for (int a = 0; a < arr.length; a++) {
System.out.println(arr[a]);
}
}
}
class Bb{
public void test1(int[] arr){
arr[0] = 100;
System.out.println("类方法中循环输出");
//遍历数组
for (int a = 0; a < arr.length; a++) {
System.out.println(arr[a]);
}
}
}
- 1.例题3:
package com.jianqun.package01;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-01-10:15
*/
public class Object05{
public static void main(String[] args){
Person p = new Person();
p.name = "李四";
p.age = 105;
B b = new B();
b.test2(p);
}
}
class Person{
String name;
int age;
}
class B{
public void test2(Person p){
Person person = new Person();
person.age = 10;
person.name = "张三";
}
}
- 1.例题4:
package com.jianqun.day08;
public class TransferTest3 {
public static void main(String[] args) {
TransferTest3 transferTest3 = new TransferTest3();
transferTest3.first();
}
public void first(){
int i = 5;
Value value = new Value();
value.i = 25;
second(value,i);
System.out.println(value.i);//20
}
public void second(Value v,int i){
i = 0;
v.i = 20;
Value value = new Value();
v = value;
System.out.println(v.i + "::" + i);//15::0
}
}
class Value{
int i = 15;
}
- 5.例题5:
重写println方法,这个题目并不是简单得的数值交换,在实现的时候,不可以直接使用基本类型的数值交换
g.方法的overload(重载):
g1.基本概念
- java中在
同一个类
中可以有同名方法
的存在,但是要求形参列表不一致(参数个数不同或者参数类型不同)
,跟方法的返回值,方法修饰符。方法参数的名称都没有任何关系
g2.重载的好处
- 可以减少方法起名字的麻烦
- 可以减小记方法名的麻烦
g3.实现重载
- 1.重载的方法名必须相同
- 2.形参列表:必须不同(形参类型或者个数,参数名字无所谓)
- 3.
返回类型:可以相同,也可以不同
h.可变个数形参的方法:
- 1.是在JDK5.0新增的内容
h1.基本语法:
访问修饰符 返回值类型 方法名(数据类型... 形参名)
{
//代码
}
h2.具体使用:
- 1.可变参数的个数可以是0或者多个
- 2.可变参数的
实参可以是数组
- 3.可变参数的
本质就是数组
,也就是说可变个数形参的方法
与同名的方法、参数类型相同但形参是数组
的情况不可以同时存在
- 4.可变参数
可以与普通型参数一起
,但是必须保证可变参数在后面
- 5.一个形参
只能有一个可变参数
- 6.可变参数的方法与本类中
同名的但形参个数不同
的方法之间构成了重载
package com.jianqun.package01;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-01-20:53
*/
public class Object08 {
public static void main(String[] args) {
int[] arr = {1,2,12};
HspMethod hspMethod = new HspMethod();
hspMethod.sum(arr);
}
}
class HspMethod{
// public int sum(int n1,int n2){
// return n1 + n2;
// }
// public int sum(int n1,int n2,int n3){
// return n1+ n2;
// }
/**
*
* 优化:使用可变参数进行优化
*/
public int sum(int... nums){
System.out.println("接受的参数个数量可变" + nums.length);
int res = 0;
for (int i = 0; i < nums.length; i++) {
res += nums[i];
}
System.out.println(res);
return res;
}
}
i.递归方法:
- 1.递归方法:一个方法体内调用它自身
- 2.方法递归包含了一种隐士的循环,它会重复执行某段代码,但是这种重复执行无需循环控制
i1.递归调用的内存分析
i2. 递归之阶乘举例分析:
i3. 递归的重要原则
- 1.执行一个方法的时候,就会创建一个新的受保护的独立空间(栈空间)
- 2.方法的局部变量是独立的,不会相互影响
- 3.如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据
- 4.当一个方法执行完毕后,或者遇到return就会返回。遵守谁调用就把结果返回给谁,同时当方法执行完毕或者返回时,该方法就执行完毕了。
i4.实现斐波那契
- 斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……
其规律很明显,从第3个数开始,每个数都等于它前两个数的和。
package com.jianqun.package01;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-01-16:01
*/
public class Object06 {
public static void main(String[] args) {
To t = new To();
System.out.println("当n=7的时候,斐波那契数是:" + t.fibonacci(7));
}
}
class To {
/**
* 递归实现斐波那契数:1 1 2 3 5 8 13........
**/
public int fibonacci(int n){
if (n >=1){
if (n==1 || n==2){
return 1;
}else{
return fibonacci(n-1) + fibonacci(n-2);
}
}else{
System.out.println("输入的数据错误");
return -1;
}
}
}
4.类的成员 -> 构造器(构造方法)Constructor
4.1.基本语法
1.[修饰符] 方法名(形参列表){方法体}
4.2.构造器作用
- 构造器的
主要作用是创建新的对象及其对新对象的初始化
,构造器是用来造对象的
4.3.构造器特点
- 1.构造器的
修饰符可以是默认的,也可以是 public ,protected,private
- 2.构造器
没有返回值
- 3.
方法名和类名必须一致
- 4.参数列表和成员方法的规则一样
- 5.在创建对象的时候,系统会
自动的调用该类的构造器完成对象的初始化
- 6.如果我们没有显示的调用构造器,系统就会默认使用无参构造器
4.4.构造器快速入门
package com.jianqun.package02;
/**
* @author jianqun
* @email:1033586391@qq.com
* @creat 2022-02-02-10:01
*/
public class Constructor01 {
public static void main(String[] args) {
//当我们new一个对象的时候,直接是通过构造器指定名字和年龄
//创建对象的时候就直接指定对象的名字和年龄
Person3 smith = new Person3("smith", 80);
System.out.println("p1的信息如下" + smith.name + smith.age);
}
}
class Person3{
String name;
int age;
//构造器
//构造器名字和类名一致
//构造器无返回值,不可以写void
//(String name, int age)是构造器的形参列表,和成员方法一个样
public Person3(String name, int age) {
this.name = name;
this.age = age;
}
}
- 如果程序员没有自定义构造器,那么
系统会自动默认生成一个无参构造器
- 一
旦自己定义了构造器,那么默认的无参构造器就没了
,除非自己显示定一下cc - 一个类中可以含有多个构造器,构造器之间构成
重载的
关系
4.5.对象创建的流程分析
- 1.在
方法区加载Person类
- 2.在堆中
分配空间
- 3.完成
对象的初始化
,默认初始化中:age = 0;name = null
; - 4.
显示初始化
:age = 90;name = null; - 5.
构造器初始化
:age = 20,name = “小倩” - 6.把
对象在堆中的地址返回给p(P就是对象的引用)
5.类成员-代码块
5.1.代码块有什么作用:
- 1.代码块
又叫初始化快
,属于类中的成员
,类似于方法,是将逻辑语句封装在一个语法体中,通过{}包围起来
- 2.代码块分两类:
静态代码块和非静态代码块
,静态内部类随着类的加载而执行;非静态代码类随着对象的创建而执行 - 3.代码块作用是:
初始化类、对象
- 4.代码块和方法不同的是:
没有方法名,没有返回值,没有参数,只有方法体
,且不能通过对象或者类来进行显示调用,而是加载类时候,或创建对象的时候来隐式调用
5.2.语法
修饰符{
//代码
}
- 1.修饰符是可选的,要是写的话,也是只能写static
- 2.逻辑语句是可以为任意逻辑语句
(输入,输出,方法调用,循环,判断)
- 3.
;
可以写,也可以不写
5.3.代码块使用的注意事项:
1.类加载的时机:
2.静态代码类与非静态代码类对比:
5.4.演示
a.案例演示1:代码块简化构造器中重复语句
代码块相当于另外一种形式的构造器(对构造器哟补充作用),可以做初始化操作
1.场景:当多个构造器中有相同的重复语句时
,可以初始化到代码块中,提高代码的重用性
2.代码块解决:代码块的调用要优先于构造器
b.案例演示2:代码块使用注意事项;
package com.jianqun.static_;
/**
* @author: jianqun
* @email: 1033586391@qq.com
* @creat: 2022-04-04-13:28
* @Description:
*/
public class CodeBlockDetail01 {
public static void main(String[] args) {
//1.创建对象实例,虽然创建了两个对象,但是静态代码块只被调用一次
CC cc1 = new CC();
CC cc2 = new CC();
//2.创建子类对象实例,父类也会被加载
AA aa2 = new AA();
//3.调用静类的静态成员时(静态属性和静态方法)
System.out.println(Cat.n1);
}
}
class CC{
static {
System.out.println("CC 静态代码块被调用");
System.out.println("==================");
}
{
System.out.println("普通代码块");
}
}
class Cat{
public static int n1 = 9999;
static {
System.out.println("==================");
System.out.println("Cat 静态代码块被调用");
}
{
System.out.println("Cat普通代码块");
}
}
class BB{
static {
System.out.println("BB 静态代码块被调用");
}
}
class AA extends BB{
static {
System.out.println("AA 静态代码块被调用");
}
}
c.案例演示3:代码块、静态代码块、构造器调用顺序:
1.创建对象的时候,,在一个类中调用的顺序是:
package com.jianqun.static_;
/**
* @author: jianqun
* @email: 1033586391@qq.com
* @creat: 2022-04-04-13:28
* @Description:
*/
public class CodeBlockDetail02 {
public static void main(String[] args) {
FF ff = new FF();
}
}
class FF{
//静态属性初始化
private static int n1 = getN1();
//静态代码块
static {
System.out.println("AAA 静态代码块");
}
public static int getN1(){
System.out.println("getN1被执行了");
return 100;
}
}