java程序基本的单位是类(class)。
在面向对象中,类也是它的重要内容。
Java数据类型:基本数据类型;引用数据类型。
引用数据类型:String、Scanner……,他们都是预先写好的类,把他们当做数据类型来使用。一定意义上来说,类也可以称为引用类型。
String str =new String();定义类的格式:[修饰符] class 类名{ //定义属性 //定义方法 //定义构造器方法}练习:定义一个类Person,将这个类作为引用数据类型,再定义测试类,测试Person引用数据类型。
class Test{public static void main(String[] args){Person p = new Person();//设置属性p.name = "zhangsan";p.age = 18;//调用方法p.getInfo();}}class Person{//定义属性String name; int age; //定义方法void getInfo(){System.out.PRintln("name"+name+"/n age"+age); }}
什么是对象?
对象,是一个具体存在的事物,他具有属性和行为(方法)。如:人,电脑,食物。
类和对象的关系:
类:说明书,图纸;
如果对象是建筑的话,类就是建筑的图纸;
对象是食物的话,类就是菜谱;
类就是用来描述对象的,描述对象具有什么属性,什么行为,类定义了对象。
类是:抽象的,对象就是具体的。
类与对象存在的关系:
对象是通过类创造的,那么类是优先于对象存在而存在。换句话说,类存在,对象不一定存在,但是对象存在了,类一定存在。
注意:“对象存在,类不存在”是不可能的,如果图纸都没有,那么怎么去盖房?
静态修饰符 static:
static只能修饰类的成员。
static 修饰变量:
static 类型 变量名;
static 返回值 方法名(){}
Static修饰的成员:是静态的,直接属于类,而不属于类创造出来的对象,随着类的创建而创建,随着类的消失而消失。
当类存在的时候,被static修饰的成员就一起存在了。
没有用static修饰的成员,当类存在的时候,这些成员并不存在。
这个时候,使用类名.静态成员是OK的,但是使用类名.非静态成员,是错误的,因为非静态成员并不是与类一起产生,那么使用一个存在的东西去访问一个不存在的东西,肯定是不行的!
怎么访问没有被static修饰的非静态成员?
可以通过new关键字创建该类对象,使用对象.非静态成员方式调用,没有被static修饰的非静态修饰的成员只属于创造出来的对象本身。
存在的顺序:类、静态成员优先于对象、非静态成员存在。
提示:按照存在顺序可以得出,静态成员只能调用、访问静态成员,不能访问非静态成员;非静态成员可以访问静态成员。
class%20Test{%20%20%20%20publicstatic%20void%20main(String[]%20args){%20%20%20%20%20%20%20%20//静态成员是与对象一起存在,所以可以通过类名.静态成员方式调用%20%20%20%20%20%20%20%20System.out.println(Animal.zhonglei);%20%20%20%20%20%20%20%20//cat是非静态成员,Aniaml调用这个时候还不存在的成员,会报错%20%20%20%20%20%20%20%20System.out.println(Animal.cat);%20%20%20%20%20%20%20%20Animalani%20=%20new%20Animal();%20%20//创建对象后,可以使用对象.非静态成员方式调用,也就是说,非静态成员属于对象%20%20%20%20%20%20%20%20System.out.println(ani.cat);%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//使用对象.静态成员%20不报错,因为静态成员优先于对象而存在。%20%20%20%20%20%20%20%20System.out.println(ani.zhonglei);%20%20%20%20%20%20%20}}class%20Animal{%20%20%20%20staticString%20zhonglei%20=%20"动物";%20%20%20%20Stringcat="猫";}%20class%20%20Person{%20%20%20%20String%20a%20="aa";%20%20%20%20staticString%20b%20="bb";%20%20%20%20//验证静态成员调用非静态成员%20%20%20%20//静态方法,调用非静态成员是错误的!%20%20%20%20/*staticvoid%20m1(){%20%20%20%20%20%20%20%20a%20="abc";%20%20%20%20}*/%20
%20%20%20//验证非静态成员调用静态成员.%20%20%20%20void%20m2(){%20%20%20%20%20%20%20%20b%20="abc";%20%20%20%20}}直接类名调用成员和创建对象调用成员的区别:
类名调用成员,只能调用静态成员,不能调用非静态成员。
对象调用成员,既可以调用非静态成员,也可以调用静态成员,也就是说,非静态成员只属于它们的对象。
对象与对象之间的关系与区别:
使用同一个类Dog创建出来的对象,是两个具体存在的事物,不是同一个,他们虽然类型和属性相同,但是互不影响,他们都是独立存在的个体。
N个对象与静态成员之间的关系:
静态成员直接属于类,是唯一的。对象也可以直接访问静态成员,所以说,N多个该类的实例对象访问的静态成员其实是同一个,换句话说,静态成员被N多个实例对象共享。
特殊的成员:构造器方法
构造器方法:是用来构造对象的,当我们使用new关键字创建对象的时候,这个创建过程是一个行为、动作。其实他也是一个方法,只不过我们以前是没有注意过这个方法。
定义格式:
public%20类名([参数类型%20参数名]){
%20//代码
}%20
使用方式:
构造器方法,当我们使用new关键字创建对象的时候调用。
new%20Animal();//这个时候,实际上是调用了对象的构造器方法。如果我们在定义对象的时候,没有写构造器方法,就会隐式的存在一个无参的构造器方法。class%20Animal{%20%20%20%20staticString%20zhonglei%20=%20"动物";%20%20%20%20Stringcat;%20%20%20%20Stringage;}%20当我们定义了构造器方法,那么这个无参构造器就消失了。
class%20Animal{%20%20%20%20%20publicAnimal(String%20a){%20%20%20%20%20%20%20%20age%20=a;%20%20%20%20}%20%20%20%20staticString%20zhonglei%20=%20"动物";%20%20%20%20Stringcat;%20%20%20%20Stringage;}%20当我们定义了构造器,并且指定了构造器需要的传参参数,之前隐式的空构造器方法就会消失。
对象创建后,对象的成员的默认值:
Int:0
Byte:0
Long :0
Short :0
Double:0.0
Float:0.0
Char:’’//编码表里面编码为0的那个字符
Boolean:false
引用数据类型:null
对象的引用和生命周期:
对象的创建:
使用new关键字创建对象,在堆空间中,开辟一块区域用来存放这个对象的数据,然后将这个对象的门牌号(地址值)赋值给栈空间中该类型变量。
引用:栈空间中的变量指向堆空间中的对象。
用手机号绑定QQ账号,使用手机号登陆QQ和使用QQ号登陆QQ,登陆的是同一个账户。那么使用手机号登陆QQ后,发了一条朋友圈,再使用QQ账号登陆,那条朋友圈信息还在。
栈空间中的变量可以有N个同时指向堆空间中的同一个对象。那么使用这几个引用变量去访问数据,其实访问的是同一个数据。
%20
%20%20%20%20%20%20%20%20//dog1存储的是指向dog对象的地址Dogdog1%20=%20new%20Dog();%20%20%20%20%20%20%20%20dog1.name=%20"哈士奇";%20%20%20%20%20%20%20%20dog1.age=%203;%20%20%20%20%20%20%20%20Dogdog1_1%20=%20dog1;%20%20%20%20%20%20%20%20System.out.println(dog1_1.name);%20%20%20%20%20%20%20%20dog1_1.name=%20"泰迪";%20%20%20%20%20%20%20%20System.out.println(dog1.name);分析:定义dog1指向一个对象,将他存储的地址赋值给dog1_1,那么使用dog1_1和dog1去访问、操作的其实是同一个对象。
对象的消失:
%20当没有引用(变量)指向对象时候,对象无法被访问和操作了。那么在堆空间中的对象就是垃圾。
%20Java提供一个垃圾回收机制,GC,通过该线程不定时的回收垃圾(没有引用指向的对象)。
//对象没用了,那么怎么回收对象所占用的内存空间 //将引用指向对象的连接中断就可以了。 dog1 =null; //System.out.println(dog1.name);空指针异常 dog1_1=null; /*这个时候,已经没有任何引用指向之前定义的对象 那么之前的那个对象就是垃圾了,java的GC会不定时 清理垃圾 */构造器:
用来创建对象,使用new关键字创建对象,实际上就是调用该对象的构造器方法。
构造器方法与普通方法区别:
1、 没有返回值,不能使用return
2、 调用方式是使用new关键字调用,而方法是通过 类名.方法名调用。
3、如果没有定义构造器方法,那么java会有一个隐藏的无参构造器,如果定义了构造器方法,那么该隐藏的无参构造器就消失。
构造器除了用来创建对象,还可以做一些对象初始化动作。
class Test{ publicstatic void main(String[] args){ Dogdog1 = new Dog(); System.out.println(dog1.name); } }class Dog{ //在创建Dog类型对象时,对象的属性就有初始值。 publicDog(){ name ="哈士奇"; } staticString aixinjiayuan = "爱心家园"; Stringname;}还可以传参给构造器,用来初始化数据。class Test{ publicstatic void main(String[] args){ Dogdog1 = new Dog("金毛"); System.out.println(dog1.name); Dogdog2 = new Dog("哈士奇"); System.out.println(dog2.name); } }class Dog{ //在创建Dog类型对象时,对象的属性就有初始值。 publicDog(String str){ name =str; } staticString aixinjiayuan = "爱心家园"; Stringname;}this 关键字:
代表所在的类中创建出来的对象本身。
class Dog{ //在创建Dog类型对象时,对象的属性就有初始值。 //遇到局部变量与外部变量重名,可以使用this找到外部变量。 //this代表当前创建的对象本身。 publicDog(String name){ this.name= name; } staticString aixinjiayuan = "爱心家园"; Stringname;}方法的定义:具有一定功能的代码块,有返回值,也可以传参。
定义格式:
[修饰符] 返回值方法名([参数类型参数名称]){
//0到多行代码块
}
方法的重载:
在一个类里面,可以定义n多个同名方法,只需要参数列表不同即可。
重载只与形参列表有关,与返回值、修饰符无任何关系。
publicstatic int add(int a , int b){ returna+b ; } publicstatic int add(int a , int b, int c){ returna+b+c ; } publicstatic int add(int a , int b, int c,int d){ returna+b+c+d ; }构造器是特殊的方法,那么构造器也可以重载: publicDog(String name){ this.name= name; } publicDog(String name ,int age){ this.name= name; this.age= age; } staticString aixinjiayuan = "爱心家园"; Stringname; int age;参数列表的可变长参数:
当我们遇到需要传递同一种参数类型的数据,但是参数个数较多,这个时候如果依次重载不同参数列表的方法,就显得代码臃肿。
如:遇到如下情况,就需要重载4个add方法。
result=AddMethod.add(1,2); System.out.println(result); result=AddMethod.add(1,2,3); System.out.println(result); result=AddMethod.add(1,2,3,4); System.out.println(result); result=AddMethod.add(1,2,3,4,5);解决这个问题,可以使用可变参数。
作用:接收同一种数据类型的数据,但是接收的参数个数是可以变化的。
接收过来以后,java自动将接收的数据封装到数组里面,在方法的代码块中,这个参数就是一个该类型的数组。我们将它当成普通数组使用即可。
问题:数组是一个不可改变长度的容器,为什么在使用的时候,可以传递不同长度的数据?
这里的可变参数数组的定义,是根据传递过来的参数来定义。
定义格式:
[修饰符] 返回值类型方法名(参数类型…参数名){
//参数名就是一个该参数类型的数组。
}
注意:可变参数,放置的位置只能是在方法参数列表的最后一个参数的位置。并且,一个方法参数列表中只能有一个可变参数。
publicstatic int add(String str, int ...arr){ intresult =0; for(inti = 0;i < arr.length ; i++){ result+=arr[i]; } returnresult; }特殊的方法调用:递归
递归:自己调用自己。方法内部代码调用方法本身。
class%20Test2{static%20int%20method(int%20i){%20%20%20%20if(i%20==1){%20%20%20%20%20%20%20%20returni%20;%20%20%20%20}%20%20%20%20int%20result=%20method(i%20-%201);%20%20%20%20returnresult;}%20public%20static%20void%20main(String[]%20args){%20%20%20%20int%20%20result%20=%20method(5);%20%20%20%20System.out.println(result);}}案例:阶乘
阶乘:5的阶乘是%201*2*3*4*5 %206的阶乘是1*2*3*4*5*6%20从1到它本身的整数相乘。
使用for循环求阶乘:
使用递归算法求阶乘:
class JieCheng{public static void main(String[] args){int result = jiecheng(3);System.out.println(result);}public static int jiecheng(int num){ if(num ==1){ returnnum; } num = num * jiecheng(num -1) ; return num; }}成员变量和局部变量:
成员变量:在成员位置,属于对象或者是类。随着类或对象的创建而创建,消失而消失。
局部变量:定义在方法中,随着方法的创建而创建,随着方法的消失而消失。
//成员变量 Stringchengyuan; //成员方法 publicvoid method(){ //局部变量 Stringjubu; }
形参:定义在方法参数列表中,表示一个参数的类型和参数名。
实参:方法执行时候,传递进来的实际参数(值)。
变量在内存中的生命周期:
类变量:与类同时创建,与类同时消失。
实例变量:创建对象时,创建实例变量,对象被回收,属于该对象的实例变量消失。
局部变量:方法被调用,局部变量被创建,方法执行完成,局部变量被回收。
代码块:执行一段代码,没有名称,没有返回值,没有参数,不能被调用。
静态代码块:类存在了(类加载到内存当中),执行静态代码块中的代码,并且只会执行一次。
class Test{ //类加载到内存中就执行该代码块 static { System.out.println("静态代码块执行了"); } publicstatic void main(String[] args){ } } 第二种情况:class Test{ publicstatic void main(String[] args){ Dog dog1 =new Dog(); } }class Dog{ //类加载到内存中就执行该代码块 static { System.out.println("静态代码块执行了"); }} 构造代码块:对象创建(new Dog()),执行一遍构造代码块,并且只会执行一次。class Test{ publicstatic void main(String[] args){ Dog dog1 =new Dog(); Dog dog2 =new Dog(); } }class Dog{ //对象一旦创建就执行该代码块 { System.out.println("普通代码块执行了"); }}代码块的作用:就是初始化对象、初始化类时候做一个初始化动作,如:赋值操作。
类、对象产生的顺序及在内存中的存储:
类加载到内存,通过类名调用静态方法,如:类名.静态方法;通过类创建对象,new 对象()。
对象加载到内存,就是new关键字创建后加载到内存。
静态成员、静态代码块、实例变量、构造代码块、构造方法
以new对象为例,说明类和对象中数据以及代码块执行的顺序:
class Test{ publicstatic void main(String[] args){ Dog dog1 =new Dog(); //当我执行new Dog()会发生了什么事情? /* 1、加载类到静态区域 2、先创建静态成员 3、执行静态代码块 4、创建实例变量 5、构造代码块 6、构造方法 */ }}class Dog{ //如果不给静态成员初始化值,会有默认初始值 staticString aixinjiayuan = "abc"; Stringname = "泰迪"; staticvoid jingtai(){ intnum = 0; } voidshili(){ Stringstr = ""; } //静态代码块 static { System.out.println(aixinjiayuan); System.out.println("普通代码块执行了"); } //对象一旦创建就执行该代码块 { System.out.println(name); System.out.println("普通代码块执行了"); } publicDog(){ System.out.println("构造方法执行了"); }}
新闻热点
疑难解答