類和對象的初步認識
定義類和對象
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 Test
{
publicstatic void main(String[] args){
//靜态成員是與對象一起存在,是以可以通過類名.靜态成員方式調用
System.out.println(Animal.zhonglei);
//cat是非靜态成員,Aniaml調用這個時候還不存在的成員,會報錯
System.out.println(Animal.cat);
Animalani = new Animal();
//建立對象後,可以使用對象.非靜态成員方式調用,也就是說,非靜态成員屬于對象
System.out.println(ani.cat);
//使用對象.靜态成員 不報錯,因為靜态成員優先于對象而存在。
System.out.println(ani.zhonglei);
}
}
class Animal
{
staticString zhonglei = "動物";
Stringcat="貓";
}
class Person
{
String a ="aa";
staticString b ="bb";
//驗證靜态成員調用非靜态成員
//靜态方法,調用非靜态成員是錯誤的!
/*staticvoid m1(){
a ="abc";
}*/
類和對象及方法的的初步認識類和對象的初步認識 //驗證非靜态成員調用靜态成員.
void m2(){
b ="abc";
}
}
直接類名調用成員和建立對象調用成員的差別:
類名調用成員,隻能調用靜态成員,不能調用非靜态成員。
對象調用成員,既可以調用非靜态成員,也可以調用靜态成員,也就是說,非靜态成員隻屬于它們的對象。
對象與對象之間的關系與差別:
使用同一個類Dog建立出來的對象,是兩個具體存在的事物,不是同一個,他們雖然類型和屬性相同,但是互不影響,他們都是獨立存在的個體。
N個對象與靜态成員之間的關系:
靜态成員直接屬于類,是唯一的。對象也可以直接通路靜态成員,是以說,N多個該類的執行個體對象通路的靜态成員其實是同一個,換句話說,靜态成員被N多個執行個體對象共享。
特殊的成員:構造器方法
構造器方法:是用來構造對象的,當我們使用new關鍵字建立對象的時候,這個建立過程是一個行為、動作。其實他也是一個方法,隻不過我們以前是沒有注意過這個方法。
定義格式:
public 類名([參數類型 參數名]){
//代碼
}
使用方式:
構造器方法,當我們使用new關鍵字建立對象的時候調用。
new Animal();//這個時候,實際上是調用了對象的構造器方法。如果我們在定義對象的時候,沒有寫構造器方法,就會隐式的存在一個無參的構造器方法。
class Animal
{
staticString zhonglei = "動物";
Stringcat;
Stringage;
}
當我們定義了構造器方法,那麼這個無參構造器就消失了。
class Animal
{
publicAnimal(String a){
age =a;
}
staticString zhonglei = "動物";
Stringcat;
Stringage;
}
當我們定義了構造器,并且指定了構造器需要的傳參參數,之前隐式的空構造器方法就會消失。
類和對象及方法的的初步認識類和對象的初步認識
類和對象及方法的的初步認識類和對象的初步認識
對象建立後,對象的成員的預設值:
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個同時指向堆空間中的同一個對象。那麼使用這幾個引用變量去通路資料,其實通路的是同一個資料。
類和對象及方法的的初步認識類和對象的初步認識
類和對象及方法的的初步認識類和對象的初步認識 //dog1存儲的是指向dog對象的位址
Dogdog1 = new Dog();
dog1.name= "哈士奇";
dog1.age= 3;
Dogdog1_1 = dog1;
System.out.println(dog1_1.name);
dog1_1.name= "泰迪";
System.out.println(dog1.name);
分析:定義dog1指向一個對象,将他存儲的位址指派給dog1_1,那麼使用dog1_1和dog1去通路、操作的其實是同一個對象。
對象的消失:
當沒有引用(變量)指向對象時候,對象無法被通路和操作了。那麼在堆空間中的對象就是垃圾。
Java提供一個垃圾回收機制,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 Test2{
static int method(int i){
if(i ==1){
returni ;
}
int result= method(i - 1);
returnresult;
}
public static void main(String[] args){
int result = method(5);
System.out.println(result);
}
}
案例:階乘
階乘:5的階乘是 1*2*3*4*5 6的階乘是1*2*3*4*5*6 從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("構造方法執行了");
}
}