文章目录
类与对象
类是数据类型,类包含属性和方法(行为)。类是抽象出来的特性,对象是具体的实例
比如:int 是整型数据类型,10是具体的数
为什么要使用类
public static void main(String[] args){
//存储两只猫的信息
//1.单独变量==>不利于数据的管理
String cat1Name="小白";
int cat1Age=3;
String cat1Color="白色";
String cat2Name="小黑";
int cat2Age=1;
String cat2Color="黑色";
//2.数组==>数据类型体现不出来,只能通过下标获取信息,变量名和内容的对应关系不明确
String[] cat1={"小白","3","白色"}
String[] cat2={"小黑","1","黑色"}
//使用类
//new Cat() 创建一只猫
//Cat cat1=new Cat();把创建的猫赋给cat1
//Cat是一个类,(name,age,color)是Cat类的属性; cat1/cat2 是一个对象,
Cat cat1=new Cat();
cat1.name="小白";
cat1.age=3;
cat.color="白色";
//创建第二只猫
Cat cat2=new Cat();
cat2.name="小黑";
cat2.age=1;
cat2.color="黑色";
//访问属性,对象.属性
System.out.println("第一只猫信息"+cat1.name+" "+cat1.age+" "+cat1.color)
System.out.println("第二只猫信息"+cat2.name+" "+cat2.age+" "+cat2.color)
}
Class Cat{
String name; //属性,成员变量,字段(叫法不同)
int age; //属性有默认值,规则和数组一样,这里age=0,name=null,color=null
String color;//属性可以是基本数据类型,也可以是引用类型(对象,数组)
}
类在内存中存放的形式
如下两张图:注意(字符串在常量池中存放,堆里存的是地址)
栈:一般存放基本数据类型(局部变量) \textcolor{green}{栈:一般存放基本数据类型(局部变量)} 栈:一般存放基本数据类型(局部变量)
堆:存放对象( c a t ,数组等) \textcolor{green}{堆:存放对象(cat,数组等)} 堆:存放对象(cat,数组等)
方法区:常量池(常量,比如字符串),类加载信息(属性和方法 / 类信息只会加载一次) \textcolor{green}{方法区:常量池(常量,比如字符串),类加载信息(属性和方法/类信息只会加载一次)} 方法区:常量池(常量,比如字符串),类加载信息(属性和方法/类信息只会加载一次)
创建对象的流程分析
1.先加载类信息(Cat)(只加载一次)
2.在堆中分配空间,进行默认初始化
3.把地址赋给对象名(cat)
4.进行指定初始化,如:cat.name="小白"
成员方法
成员方法(简称方法)
为什么需要方法,比如人类:除了属性(年龄,姓名)还有一些行为,如,说话,跑步。方法相当于对象的行为
方法的基本语法
public 返回数据类型 方法名 (形参列表) {//方法体
语句;
return //(不是必须,看返回数据类型);
}
方法使用细节
public static void main(String[] args){
//方法相当与一个工具,需要调用
//先创建一个对象,然后调用方法
Person p1=new Person();
p1.speak();//调用方法,会输出“我是一个好人”
}
Class Person{
String name;
int age;
//speak成员方法,输出“我是一个好人”
//public 访问修饰符,表示方法是公开的
//void:表示方法没有返回值
//speak():speak是方法名,()是形参列表
//{}是方法体,内容是执行的代码
public void speak(){
System.out.println("我是一个好人")
}
}
//形参列表:
//1.一个方法可以有0个参数,或者多个
//2.参数类型可以任意(基本数据类型,引用类型)
//3.方法定义时的参数是形式参数,方法调用时传入的是实际参数,形参和实参的类型要一致或者兼容,个 数,顺序必须一致
//返回值:
//1.一个方法只有一个返回值,但是通过返回数组得到多个值,
//2.返回类型可以为任意类型(基本数据类型,引用类型),
//3.返回类型必须与return的值类型一致或者兼容
//4.如果方法是void,则方法体中可以没有return语句,或者只写return
//5.方法命名,驼峰命名法,getSum,一般见名知义
//方法能调用,不能嵌套定义,下面的两种方法调用规则,都是在一个方法里调用另外一个方法
//要想得到输出(print打印的内容),需要先创建对象(还有其他不创建对象也能调用(静态方法))
class A{
public void print(int n){
System.out.println("print()方法被调用n="+n);
}
public void say(){
print(10);//1.同一个类中的方法,直接调用
System.out.println("say方法被调用");
}
//2.跨类中的方法A类调用B类的方法:需要在A类方法中创建B类的对象,通过对象名调用,注意访问修饰符
public void m1(){
B b=new B();
b.hi();
}
}
Class B{
public void hi(){
System.out.println("B类hi()方法被调用");
}
}
方法传参的机制
1.基本数据类型,传递的是值拷贝,形参的改变不影响实参,swap栈里的数据会交换,main栈的值还是原来的
2.引用数据类型,传递的也是值,但是值是地址
方法的调用机制
重载
Java中允许同一个类中,多个同名的方法存在,但要求:
方法名必须相同,
参数列表必须不同,只有参数名不同不是重载
返回类型:无要求
calculate(int n1,int n2)//比较的对象,下面的方法和这个对比
calculate(int a1,int n2)//这个不是重载,下面的都是重载
calculate(int n1,double n2)
calculate(double n1,int n2)
calculate(int n1,int n2,int n3)
可变参数
java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。
基本语法:访问修饰符 返回类型 方法名(数据类型… 形参名){}
class Method{
public int sum(int n1,int n2){
return n1+n2;
}
public int sum(int n1,int n2,int n3){
return n1+n2+n3;
}
public int sum(int n1,int n2,int n3,int n4){
return n1+n2+n3+n4;
}
//使用可变参数
public int sum(int... nums){
int res=0;
for(int i=0;i<nums.length;i++){
res+=nums[i];
}
return res;
}
}
//上面的前三个方法名称相同,功能相同,参数不同==>使用可变参数
//1.int... 表示接收的是可变参数,类型是int ,即可以接收多个int(0~多)
//2.使用可变参数时,可以当做数组来使用,即nums可以当做数组
//使用细节:
//1.可变参数的实参可以为0个或任意多个
//2.可变参数的实参可以为数组
//3.可变参数的本质就是数组
//4.可变参数可以和普通类型的参数一起放到形参列表,但必须保证可变参数在最后
//5.一个形参列表中只能出现一个可变参数
public class Var{
publics static void main(String[] args){
int[] arr={1,2,3};
T t1=new T();
t1.f1(arr);
}
}
Class T{
public void f1(int... nums){
System.out.println("长度="+nums.length);
}
public void f2(double n1,int... nums){}//细节4
public void f2(double... n,int... nums){}//错误,细节5
}
作用域
java主要有成员变量(属性),局部变量(在成员方法中定义的变量,代码块中的变量)
全局变量:也就是属性,作用域为整个类体
局部变量:除属性外的其他变量,作用域为定义它的代码块中
全局变量可以不赋值,直接使用,有默认值,局部变量必须赋值后,才能使用,没有默认值
全局变量可以被本类使用,或其他类使用(通过对象调用),局部变量,只能在本类中对应的方法中使用
全局变量可以加修饰符,局部变量不可以加修饰符
public class VarScope{
public static void main(String[] args){
Person p1=new Person();
p1.say();//King 属性和局部变量可以重名,访问时遵循就近原则
//当执行say方法时,say方法的局部变量比如name,会创建,当say执行完毕后
//name局部变量就销毁,但是属性(全局变量)仍然可以使用
}
}
class Person{
String name ="jack";
public void say(){
String name="King";
//String name="queue"; 错误,在同一个作用域中,两个局部变量,不能重名(不能重复定义)
System.out.println("say() name="+name);
}
}
//属性生命周期较长,伴随着对象的创建而创建,销毁而销毁。局部变量,生命周期短,伴随着代码块的执行而创建,代码块结束而销毁。即在一次方法调用过程中。
构造器
使用构造器可以在创建对象的同时,直接指定对象的信息(年龄,姓名),主要作用是完成对新对象的初始化
基本语法:[修饰符] 方法名(形参列表){
方法体;
}
构造器使用细节
1.构造器的修饰符可以默认,也可以是public protected private
2.构造器没有返回值
3.构造器名和类名字必须一样
4.参数列表和成员方法的参数列表一样的规则
5.构造器的调用由系统完成
6.一个类可以有多个不同的构造器,构造器可以重载
7.如果程序员没有定义构造器,系统会自动给类生成一个默认的无参构造器
8.一旦定义了自己的构造器,默认的构造器就覆盖了,就无法使用默认的无参构造器,除非显式的定义一下
public class Constructor{
public static void main(String[] args){
Person p1=new Person("lin",18)
Person p2=new Person("lin")
}
}
class Person{
String name;
int age;
public Person(String pName,int pAge){
name="pName";
age=pAge;
}
public Person(String pName){
name="pName";
}
//Person(){} 默认构造器/无参构造器
}
对象创建的流程分析
1.加载类信息(Person),只会加载一次
2.在堆中分配空间(地址)
3.完成对象初始化。默认初始化age=0,name=null==>
显示初始化age=90,name=null==>
构造器初始化age=20,name=小倩
this关键字
java虚拟机会给每个对象分配this,代表当前对象,我在说“我”指的是我自己,你在说“我”指的是你
public class This{
public static void main(String[] args){
Person p1=new Person("lin",18)
Person p2=new Person("lin")
}
}
//使用细节
//1.this关键字可以用来访问本类的属性,方法,构造器
//2.this用来区分当前类的属性和局部变量
//3.访问成员方法的语法:this.方法名(参数列表)
//4.访问构造器语法:this(参数列表);注意只能在构造器中使用(在构造器中调用另外一个构造器),必须放在第一条语句
//5.this不能在类定义的外部使用,只能在类定义的方法中使用
class Dog{
String name;
int age;
public Dog(String name,int age){
this.name=name;//this.name当前对象的属性name
this.age=age;
}
public Dog(){
this("Jack",100);//细节4
System.out.println("Dog()构造器");
}
public void say1(){
System.out.println("say1()");
this.say2()//细节3
}
public void say2(){
System.out.println("say2()");
}
}
//this相当于隐藏属性,但实际上并没有,帮助理解