1. 定义
类:把某一类事物的属性提取出来,形成类,类有属性(也叫成员变量/field字段)和行为
对象:一个具体的实例
注意:从类到对象的说法:1)创建一个对象2)实例化一个对象3)把类实例化
成员方法的定义
public 返回数据类型 方法名 (形参列表){//方法体
语句;
return语句;//可有可无,void不需要
}
注意:
1. 形参列表:表示成员方法输入,如cal(int n),getSum(int n1,int n2)
2. 返回数据类型:表示成员方法输出,void表示没有返回值
入门案例:小杨养猫问题
//实例化一只猫
//new Cat()创建一只猫
//Cat cat1=new Cat();把创建的猫赋值给cat1
Cat cat1=new Cat();
cat1.name="小红";
cat1.age=423;
cat1.color="红色";
Cat cat2=new Cat();
cat2.name="小嗨";
cat2.age=45;
cat2.color="蓝色";
//如何访问对象的属性
System.out.println("第一只猫:"+cat1.name+" "+cat1.age+" "+cat1.color);
}
}
class Cat{
//定义一个猫类,里面可以放属性和行为
//属性,可以是基本数据类型也可以是引用类型(对象、数组)
String name;
int age;
String color;
}
2. 对象在内存中的存在形式
对象和数组都是引用类型(引用地址)
类首先把属性信息加载到方法区
然后开始分配空间,类是引用数据类型,引用的地址在堆中
然后分配不同的空间,如果是字符串(字符串也是引用类型),地址指向常量池;如果是基本数据类型就放在堆中
最后把地址返回给cat
属性
3. 属性的注意事项
1)属性的定义语法和变量相同:访问修饰符 属性类型 属性名
2)属性的类型可以是任意类型,包含基本类型和引用类型
3)属性如果不赋值,默认值的规则同数组
int 0;short 0;byte 0;long 0;float 0.0;double 0.0;char \u0000;boolean false;String null
4. 创建对象的两种形式
1)先声明再创建
Cat cat;
cat = new Cat();
2)直接创建
Cat cat=new Cat();
5. 对象分配机制(赋值)
执行Person p1=new Person();
首先加载类信息(属性信息、方法信息)
然后在堆里面开空间,有空间就一定有地址,0x0011
因为有两个属性,所以空间中应该有两个存放属性的位置
因为还没有执行到赋值语句,所以此时空间里存放的是默认值0和null
然后把地址返回给栈中的p1
执行p1.age=10;
p1从地址找到默认值0并修改为10
执行p1.name="小明"
字符串常量放在常量池中,小明的地址是0x0022,回填到堆中
执行Person p2=p1;
p2开辟一个新的空间,然后把p1的地址0x0011复制粘贴过来,p1和p2指向堆里面同一个空间
Java内存结构分析
栈:存放基本数据类型(局部变量)
堆:存放对象(Cat cat,数组等)
方法区:常量池(常量,如字符串),类加载信息
方法
1. 入门案例
添加speak方法,输出我是阿屎
//先创建对象,然后调用
Person p1=new Person();
p1.speak();
}
}
class Person{
public void speak(){
//public表示方法是公开的
//void表示方法没有返回值
//speak():speak是方法名,()是形参列表
System.out.println("我是阿屎");
}
}
2.1-定义一个方法计算1-1000相加的和
Person p1=new Person();
p1.cal01();
}
}
class Person{
public void cal01(){
int sum=0;
for(int i=1;i<=1000;i++){
sum+=i;
}
System.out.print(sum);
}
}
2-2. 接收一个n,计算1-n相加的和
Person p1=new Person();
p1.cal02(5);//把5传入n
}
}
class Person{
public void cal02(int n){//有一个形参n,可以接收用户输入
int sum=0;
for(int i=1;i<=n;i++){
sum+=i;
}
System.out.print(sum);
}
}
2-3. 计算两个数的和
Person p1=new Person();
int returnSum=p1.getSum(10, 20);//定义一个变量returnSum来接收方法返回的值
System.out.println(returnSum);//如果不接收的话无法显示
}
}
class Person{
//int:表示方法执行后,返回一个int值
//(int n1,int n2)形参列表,两个形参,可以接收用户输入的2个数
//return sum表示把sum的值返回
public int getSum(int n1,int n2){
int sum=n1+n2;
return sum;
}
}
2-4 巧妙遍历二维数组
int arr[][]={{1,2,3},{4,5,6},{6,65}};
Mytools tool=new Mytools();
tool.printArr(arr);
}
}
class Mytools{
public void printArr(int arr[][]){
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
}
3. 方法的调用机制(以2-3为例)
首先在栈中开辟一个空间,叫main栈(自己起的,理解方便)
执行Person p1=new... new完过后在堆中产生一个对象,指向
执行int returnSum=... ,先执行右边然后赋值给左边,执行p1.getSum时又在栈中开辟一个独立的空间,叫getSum栈(自己起的),指向,跳转到对应的方法getSum,按照顺序对应关系把10、20分别赋值给n1、n2,接着执行sum=n1+n2
执行return sum,getSum栈中的return sum会返回main栈中int returnSum=...中的p1.getSum(10,20),把30赋给returnSum,释放getSum空间,回到main栈
执行system.out...
4. 成员方法的好处
①提高代码的复用性
②可以将实现的细节封装起来,然后由其他用户调用
5. 方法使用细节
//细节1:一个方法返回值只有一个,但是如果想得到多个结果,可以通过返回数组的方式来实现
//输出两个数的和和差
Details d1=new Details();
int arr[]=d1.resNum(4, 3);
System.out.println("和:"+arr[0]);
System.out.println("差:"+arr[1]);
}
}
class Details{
public int[] resNum(int n1,int n2){
int getNum[]=new int[2];
getNum[0]=n1+n2;
getNum[1]=n1-n2;
return getNum;
}
}
//细节2:如果方法要求有返回数据类型,则方法体中最后执行额语句必须为return,且返回值类型和return值类型一致或兼容
public double f1(){
n1=100;
return n1;//可以,因为发生了int→double的自动类型转换
}
public int f1(){
double n2=1.1;
return n2;//不可以,因为需要强转
}
//细节3:方法不能再嵌套
public void f1(){//错误
public void f2(){
}
}
//细节4:同一个类中的方法之间相互调用,不需要创建对象,直接调用即可
A a=new A();
a.sayOk();
}
}
class A{
public void print(int n){
System.out.println("print方法被调用 n="+n);
}
public void sayOk(){
print(10);
System.out.println("继续执行sayOK");//先调用print方法,执行完后再继续执行sayOK方法
}
}
//细节5:跨类中的方法A类调用B类方法,需要通过对象名调用
public static void main(String args[]){
A a=new A();
a.m1();
}
class A{
public void m1(){
System.out.println("A中的方法m1被调用");
B b=new B();
b.m();
System.out.println("A中的m1结束执行");
}
}
class B{
public void m(){
System.out.println("B中的方法m被调用");
}
}
//输出结果
A中的方法m1被调用
B中的方法m被调用
A中的m1结束执行
6. 方法练习题
思路:1方法的返回类型 2方法名 3形参 4方法体
(1)编写类AA,有一个方法:判断一个数是奇数还是偶数,返回boolean
AA a=new AA();
if(a.judge(90)){
System.out.println("奇数");
}else{
System.out.println("偶数");
}
}
}
class AA{
public boolean judge(int n){
// if(n%2==0){
// return true;
// }else{
// return false;
// }
return n%2!=0?true:false;//等价于上边的if-else语句
}
}
(2)根据行、列、字符打印,对应行数和列数的字符,比如4行4列字符#
####
####
####
####
AA a = new AA();
a.print(4, 4, '#');
}
}
class AA{
public void print(int row,int col,char c){
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
System.out.print(c+" ");
}System.out.println();
}
}
}
7. 方法传参机制
1.基本数据类型的值传递
结论:基本数据类型,传递的是值,形参的任何改变不影响实参
2. 引用类型的值传递
结论:引用类型传递的是地址,可以通过形参影响实参
3. 方法返回类型是引用类型应用实例
编写一个方法copyPerson,可以复制一个Person对象,返回复制的对象。克隆对象
*要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同
Person p=new Person();
p.name="赵";
p.age=10;
MyTools tools=new MyTools();
Person p2=tools.copyPerson(p);
System.out.println("p的属性"+p.name+"\t"+p.age);
System.out.println("p2的属性"+p2.name+"\t"+p2.age);
System.out.println(p==p2);//如果相同返回true,否则返回false
}
}
class Person{
String name;
int age;
}
class MyTools{
public Person copyPerson(Person p){
Person p2=new Person();
p2.name=p.name;
p2.age=p.age;
return p2;
}
}