目录
一.方法
1.方法的定义
注意:
方法调用实例:计算n的阶乘
2.方法的重载
例如:数字相加add方法的重载
3.方法签名
4.可变参数
5.作用域
6.实参和形参的关系
二.类和对象
1.类的定义格式 (类名注意采用大驼峰定义)
2.类的实例化
1.构造器
2.构造器举例
3.对象创建流程
3.方法传参机制(通过对象)
例如:创建一个人类
【思考题】假设在change方法中将p=null置空,那么最后结果会输出什么?
【思考题2】假设change方法如下,最后的结果会输出什么?
【思考题3】以下代码输出什么?
输出
4.什么是this引用
1)this就是当前对象的属性,方法,构造器
2)用this访问构造器:this(参数列表);只能在构造器中访问另一个构造器,且必须放在第一条语句
3)哪个对象调用,this就代表哪个对象
一.方法
1.方法的定义
// 方法定义
修饰符 返回值类型 方法名称 ([ 参数类型 形参 ...]){
方法体代码 ;
[ return 返回值 ];
}
注意:
1. 方法名字:采用 小驼峰命名
2. 在 java 当中, 方法必须写在类当中 ,方法不能嵌套定义 ,没有方法声明一说
方法调用实例:计算n的阶乘
public class TestMethod {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 5; i++) {
sum += fac(i);
}
System.out.println("sum = " + sum);
}
public static int fac(int n) {
System.out.println("计算 n 的阶乘中n! = " + n);
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
}
2.方法的重载
在 Java 中,如果多个方法的名字相同,参数列表不同,则称该几种方法被重载了
注意:
1. 方法名必须相同
2. 参数列表必须不同 ( 参数的个数不同、参数的类型不同、类型的次序必须不同 )
3. 与返回值类型是否相同无关
4. 编译器在编译代码时,会对实参类型进行推演,根据推演的结果来确定调用哪个方法
例如:数字相加add方法的重载
public class OverLoad {
public static void main(String[] args) {
int a = 10, b = 20, c = 30;
double a1 = 1.1, b1 = 2.2, c1 = 3.3;
TestMethod test = new TestMethod();
int sum1 = test.add(a,b);
int sum2 = test.add(a,b,c);
double sum3 = test.add(a1,b1);
double sum4 = test.add(a1,b1,c1);
System.out.println(sum1);
System.out.println(sum2);
System.out.println(sum3);
System.out.println(sum4);
}
}
class TestMethod{
//方法一:计算两个整数相加
public int add(int a, int b){
return a+b;
}
//方法二:计算两个小数相加
public double add(double a, double b){
return a+b;
}
//方法一:计算三个整数相加
public int add(int a, int b,int c){
return a+b+c;
}
//方法二:计算三个小数相加
public double add(double a, double b, double c){
return a+b+c;
}
}
3.方法签名
在同一个作用域中不能定义两个相同名称的标识符。比如:方法中不能定义两个名字一样的变量,那 为什么类中就 可以定义方法名相同的方法呢?
方法签名即:经过编译器编译修改过之后方法最终的名字。具体方式:
方法全路径名 + 参数列表 + 返回值类型,构成 方法完整的名字。
4.可变参数
1.基本概念:java中允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法
2.基本语法:访问修饰符 返回类型 方法名(数据类型...形参名){
}
3.注意
1)实参可为0或者任意,可以为数组,可以和普通类型放一起,但必须保证可变参数放在最后且只有一个
2)可变参数的本质就是数组
例如:以下代码中方法add可以计算n个整数相加的和并返回
public class VarParameter01 {
public static void main(String[] args) {
HspMethod test = new HspMethod();
int res = test.add(1,2,34,54,6);
System.out.println(res);
}
}
class HspMethod{
public int add(int...nums){
int res = 0;
for(int i = 0; i < nums.length; i++){
res += nums[i];
}
return res;
}
}
5.作用域
全局变量:就是属性,可以在本类使用,或者其他类(通过对象调用),可以有修饰符
局部变量:只能在本类中对应的方法中使用
6.实参和形参的关系
形参的名字可以随意取,对方法都没有任何影响,形参只是方法在定义时需要借助的一个变量,用来保存方法在调用时传递过来的值 。
在 Java 中,实参的值永远都是 拷贝 到形参中,形参和实参本质是两个实体
1.swap()交换函数为例
public class TestMethod {
public static void main(String[] args) {
int a = 10;
int b = 20;
swap(a, b);
System.out.println("main: a = " + a + " b = " + b);
}
public static void swap(int x, int y) {
int tmp = x;
x = y;
y = tmp;
System.out.println("swap: x = " + x + " y = " + y);
}
}
// 运行结果
swap : x = 20 y = 10
main : a = 10 b = 20
可以看到,在 swap 函数交换之后,形参 x 和 y 的值发生了改变,但是 main 方法中 a 和 b 还是交换之前的值,即 没有交换成功 。
【原因分析】
在 swap 方法调用时,只是将实参 a 和 b 中的值拷贝了一份传递给了形参 x 和 y ,因此对形参 x 和 y 操作不会对实参 a 和 b 产生任何影响。
注意:对于 基础类型 来说 , 形参相当于实参的拷贝 . 即 传值调用
【解决办法】:传引用类型参数 (例如数组来解决这个问题)
基本数据类型:byte、short、int、long、float、double、char、boolean
引用类型:类(class)、接口(interface)、数组(array)
public class TestMethod {
public static void main(String[] args) {
int[] arr = {10, 20};
swap(arr);
System.out.println("arr[0] = " + arr[0] + " arr[1] = " + arr[1]);
}
public static void swap(int[] arr) {
int tmp = arr[0];
arr[0] = arr[1];
arr[1] = tmp;
}
}
// 运行结果a,b的值交换成功
arr [ 0 ] = 20 arr [ 1 ] = 10
【原因分析】
二.类和对象
1.类的定义格式 (类名注意采用大驼峰定义)
// 创建类
class ClassName {
fifield ; // 字段 ( 属性 ) 或者 成员变量
method ; // 行为 或者 成员方法
}
2.类的实例化
用类类型创建对象的过程,称为类的实例化,采用new关键字,配合类名来实例化对象。
1.构造器
1)修饰符默认,没有返回值,方法名与类名一样,构造器通过调用系统完成
2)构造器是完成对象的初始化,并不是创建对象
3)构造器也可以重载(同方法一样),如果程序员没有定义构造器,系统自动生成一个默认无参构造方法.
4)基本语法
[修饰符] 方法名(形参列表){
方法体
}
2.构造器举例
public class Constructor01 {
public static void main(String[] args) {
//直接通过构造器指定对象属性的值
Person01 test = new Person01("小锦鲤",18);
System.out.println(test.name+test.age);
Person01 test1 = new Person01();
System.out.println(test1.name+test1.age);
}
}
class Person01{
String name;
int age;
//构造器
public Person01(){
age = 18;
}
public Person01(String pname, int page){
name = pname;
age = page;
}
}
3.对象创建流程
class Person01{
String name;
int age = 90;
//构造器
public Person01(String pname, int page){
name = pname;
age = page;
}
}
Person01 p = new Person01("小锦鲤",18);
【流程分析】
3.方法传参机制(通过对象)
例如:创建一个人类
public class practice {
public static void main(String[] args) {
Person person = new Person();
change(person);
System.out.println(person.name+person.age+person.sal);
}
//方法修改属性
public static void change(Person p){
p.name = "Cindy";
p.age = 18;
p.sal = 30000;
}
}
//创建一个类
class Person{
//属性
name = "小锦鲤";
age = 18;
sal = 20000;
}
【原因分析】
从上述代码可见,方法change中传入的是Person的地址,所以在方法中对其属性进行修改成功,最后输出的值是修改后的值.
【思考题】假设在change方法中将p=null置空,那么最后结果会输出什么?
public static void change(Person p){
p = null;
}
正常输出之前的属性值
【原因分析】
p=null只是把change这个栈中p中存放的地址(原本指向Person的地址)置为空,并不影响Person原来属性的值,所以还是正常输出.
【思考题2】假设change方法如下,最后的结果会输出什么?
public static void change(Person p){
p = new Person();
p.name = "Cindy";
p.age = 18;
p.sal = 30000;
}
正常输出之前的属性值
【原因分析】
参考对象的创建过程,采用new关键字下、创建了一个新的对象,在change方法中对新的对象实行进行了赋值,但是main函数输出的还是原来对象(在main函数里创建的对象)的属性值.
【思考题3】以下代码输出什么?
public class Homework08 {//公有类
int count = 9;//属性
public void count1(){
count = 10;
System.out.println(count);
}
public void count2(){
System.out.println(count++);
}
public static void main(String[] args) {
new Homework08().count1();
Homework08 test = new Homework08();
test.count2();
test.count2();
}
}
输出
【原因分析】
new Homework08().count1(); 是匿名对象,只能用一次,用完即销毁,所以即使他把count改成了10,但用完又被销毁了, Homework08 test = new Homework08(); 是一个新建的对象,所以他的初始值依然为9.
4.什么是this引用
1)this就是当前对象的属性,方法,构造器
public class Constructor01 {
public static void main(String[] args) {
//直接通过构造器指定对象属性的值
Person01 test = new Person01("小锦鲤",18);
System.out.println("test的hashCode值为:"+test.hashCode());
}
}
class Person01{
String name;
int age;
//构造器
public Person01(String name, int age){
this.name = name;
this.age = age;
System.out.println("this.hashCode值为:"+this.hashCode());
}
}
2)用this访问构造器:this(参数列表);只能在构造器中访问另一个构造器,且必须放在第一条语句
public class Homework12 {
public static void main(String[] args) {
Employee test = new Employee("小锦鲤",18,'男',30000,"主播");
System.out.println(test.name+test.age+test.sex+test.sal+test.pos);
}
}
class Employee{
String name;
int age;
char sex;
double sal;
String pos;
public Employee(String name,int age,char sex){
this.name = name;
this.age = age;
this.sex = sex;
}
public Employee(String name,int age,char sex,double sal,String pos){
//访问构造器
this(name,age,sex);
this.sal = sal;
this.pos= pos;
}
}
3)哪个对象调用,this就代表哪个对象
public class This {
public static void main(String[] args) {
Person03 p1 = new Person03("小锦鲤",18);
Person03 p2 = new Person03("锦鲤",18);
System.out.println(p1.compareTo(p2));
}
}
class Person03{
String name;
int age;
//构造器
public Person03(String name, int age){
this.name = name;
this.age = age;
}
public boolean compareTo(Person03 p){
return (this.name.equals(p.name) && this.age == p.age);
}
}
5.static修饰符
1.static修饰称为类中的静态域,直接通过类的名称来调用,
2.static修饰的属性称为类属性,在JVM的方法区存储,所有该类对象共享此区域
3.static修饰的方法称为类方法、静态方法,通过类名称直接调用
常见于工具方法Arrays.sort(int[] arr);
4.在静态域中不能直接调用成员域(成员变量以及方法都需要通过对象来调用);
在成员域中可以直接使用静态域
public class Person {
public String name;
public static int age = 18;
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "锦鲤";
System.out.println(person1.age);
Person.age = 19;
System.out.println(person1.age);
}
}
class Test{
public static void main(String[] args) {
Person p = new Person();
p.name = "测试";
Person.age = 20;
new Test().eat(p);
}
public void eat(Person person){
System.out.println(person.name+"在吃饭,他今年"+Person.age+"岁");
}
}
6.代码块
使用{}括起来的一段代码称为代码块
1.普通代码块
定义在方法中,作用域仅限于该方法
2.构造块
定义在类的内部,不加任何修饰符的代码块
构造快优先于构造方法执行,一般用于构造方法之前对某些属性进行初始化操作
3.静态代码块
静态块优先于主方法执行
定义在类的内部,使用static修饰的代码块
在类加载时由JVM只执行一次,无论后续对象的多少,都只加载一次