类和对象
类和对象初识
java中的类和对象都是比较抽象,我们可以通过实际生活中的例子加以理解!
我们天天说java是一门面向对象的编程语言,那java中的类和对象到底是个啥呢?
类
我们日常所说的类就是一种具有共性的物体,将它成为一种类,“物以类聚人以群分”就是生活中类的一种体现。
而java中的类是啥呢?
java中的类就是相当于生活中的模型(模具/图纸)
对象
对象并不是所说的对象,虽然我们时常开玩笑说,学了java不就有对象了嘛!我们可以通过java new 一个对象嘛!
可是兄弟们,并不是说学了java你就有对象了!一个物体就是一个对象,毕竟java是外国人发明的,可能中文翻译过来就成了对象!
百度中对象的意思指的是行动或思考时作为目标的事物,同时将就是一种事物!刚好对应了刚刚的类,类是一种具有相同共性的模型。比如图纸和模具。
java中的对象是啥呢?
java中的对象现实世界的实体!就是根据类(模型)创建的实例(实体)!
总结
面向对象编程思想
我们用大象放入冰箱的例子来举例!
面向过程:
打开冰箱
放入大象
关上冰箱门
面向对象
打开冰箱
储存
关闭冰箱
我们可以发现,面向对象,我们将大象放入冰箱过程的,打开,储存,关闭对象都是冰箱!这就是面向冰箱这个对象,对冰箱进行操作!
面向对象编程三部曲
找对象
创建对象
使用对象
类和类的实例化
类是一类对象的统称,对象是类的一个实例。
例如:我们盖房子的图纸就是一个类,而我们根据图纸所盖的一个房子就是一个实例,一个图纸可以实例化无数个对象!
一个类可以有无数个实例!就是说我们可以通过类实例化对象!
类在java中也是一种类型,和数组一样是一种引用类型!
使用关键字class来声明一个类:
class Animail{ //Animail是类名 //成员属性/字段/成员变量 public String name; //成员方法/行为 public void eat(){ System.out.println("Animail::eat()"); } }
对象
上面便是一个Animail类,类是一个引用类型,我们可以像数组一样实例化类的对象!
// 实例化对象 语法 <class_name> <对象名> = new <class_name>();
所以我们可以通过Animail
类来实例化一个对象!
实例化对象
public class Text{ public static void main(String[] args){ Animal animal = new Animal(); //通过new关键字通过类实例一个Animal对象 //而animal对象名就是一个Animal对象的引用 //与我们C语言中的指针有点类似 animal.name = "小橘猫"; //通过对象的引用调用实例中属性name 赋值 animal.eat(); //对象的引用调用animal中的实例方法 } }
类的实例化
类的实例化就是将好比用图纸盖房子盖房子,类只是一个图纸,实例化后才有了对象,才会占用物理空间,储存类的实例成员!
类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图
class Animal { public String name; public int age; public void eat(){ System.out.println(name+"::eat()"); } } public class Test { public static void main(String[] args) { Animal animal = new Animal(); //通过new 类实例化操作,创建了Animal的一个对象 animal.name = "小橘猫"; //而animal 是一个Animal对象的引用,相当于,开门的钥匙 animal.age = 18; //通过animal 引用可以访问类中实例化成员变量! animal.eat(); Animal anima2 = new Animal(); anima2.name = "小黄"; anima2.age = 16; anima2.eat(); } }
注意事项
new 关键字用于创建一个对象的实例。
使用 . 来访问对象中的属性和方法。
同一个类可以创建多个实例。
类的成员
成员变量/属性/字段
在类中, 但是方法外部定义的变量, 这样的变量我们称为 “字段” 或 “属性” 或 “成员变量”(三种称呼都可以, 一般不会严格区分)。
就是说成员变量/属性/字段,在类中在方法外部上方。
class Animal { //name,age都是成员变量 public String name; public int age; public void eat(){ System.out.println(name+"::eat()"); } }
注意事项
我们通过.访问成员变量
成员变量可以不初始化,并且有默认初始值!
成员变量
不同类型成员变量的初始值:
null
null为空引用不指向任何对象!类似C语言中的空指针。记得是小写!而和C语言中的NULL空指针一样,不能通过null引用进行访问实例成员,否者为报空指针异常!
我们也可以对类中的成员变量进行初始化!不过这样的操作就使得该类的实例化对象的成员变量都有相同的值,有点鸡肋!
假如我们创建一个Animal类,如果我们将成员变量name初始化成一个固定的名字!就显得很不合理,毕竟每个动物读都有自己的名字!
成员方法
用于描述对象的行为
我们已经知道方法就好比C语言中的函数!我们通过成员方法将该类的某个行为,封装成一个方法!就好比Animal类中的eat方法。然后我们通过该类对象的引用调用该方法,展现该类的某种行为!
class Animal { public String name; public int age; public void eat(){ System.out.println(name+"::eat()"); } public void setName(String name) { this.name = name; } public String getName() { return name; } } public class Test { public static void main(String[] args) { Animal animal = new Animal(); animal.setName("浩浩"); //通过类中的setName方法将animal对象name赋值 String name = animal.getName(); //getName方法获得name System.out.println(name); animal.eat(); //展现eat() 行为 }
构造方法
类中还有一种比较特殊的方法构造方法!
方法名和类名相同
基本语法
方法名和类名相同
方法无返回值
方法的参数列表(个数和种类)不做要求
一个类可以有多个构造方法,(构造方法重载)且必须有一个构造方法!
class People{ public String name; public byte age; //无参数的构造方法 public People(){ System.out.println("name:"+name); } //含有一个参数的构造方法 public People(String name){ this.name = name; } //含有两个参数的构造方法 public People(String name,byte age){ this.name = name; this.age = age; } //含有多个参数的构造方法 //........ //上面这些构造方法构造了方法重载! }
构造方法的作用
public class Test { public static void main(String[] args) { People people = new People(); //实例化一个People对象 } }
运行结果
我们运行一下发现,我们并没有调用People类中无参数的构造方法,但是运行时却调用了!!!
这是什么原因呢?
构造方法的作用
这是不得不提构造方法的作用!
如何实例化一个对象呢?
可能你会问:bug你刚刚不是讲过了吗,不就是通过new关键字实例化一个对象嘛!
确实如此,but还有些重要的细节没说。
创建一个对象先要通过类创建一个引用,然后通过引用指向一个实例化对象。其实我们也可以不通过父类引用创建一个对象,后面bug郭学习!
实例化一个对象
通过new 关键字为创建并为对象分配空间
调用该类的合适的构造方法
这时你可能又有疑问!
bug郭你刚刚创建Animal对象,也没见你类中有构造方法,更不要说调用构造方法了!
我们创建一个类时,编译器会默认给我们创建一个不带参数的构造方法,并不会在类中显示,并且该构造方法中不含有语句!
所以实例化一个对象时,都会调用该类的构造方法,如果类的创建者没有创建构造方法,编译器就会调用默认不带参数的的构造方法!
class Book{ public String name; public double price; // public Book(){ //编译器会默认帮我们创建这个不带参数的构造方法 // } }
//自己创建构造方法! class Book{ public String name; public double price; // public Book(){ //编译器会默认帮我们创建这个不带参数的构造方法 // } public Book(String name){ //当我们创建一个构造方法 } } public class Test { public static void main(String[] args) { Book book = new Book(); //创建对象需要调用合适的构造方法 } }
为啥但我们自己创建构造方法时,实例化一个对象却报了错误!
系统不是默认调用不带参数的构造方法嘛!
但我们自己书写了构造方法时,编译器就会将默认的构造方法删除,而我们 new Book();实例化对象时是要调用类中不带参数的构造方法!但是该类中已经没有不带参数的构造方法,所以报错!
创建对象时调用合适的构造方法!
class People{ public String name; public byte age; //无参数的构造方法 public People(){ System.out.println("name:"+name); } //含有一个参数的构造方法 public People(String name){ this.name = name; } //含有两个参数的构造方法 public People(String name,byte age){ this.name = name; this.age = age; } //含有多个参数的构造方法 //........ //上面这些构造方法构造了方法重载! } class Book{ public String name; public double price; // public Book(){ //编译器会默认帮我们创建这个不带参数的构造方法 // } public Book(String name){ //当我们创建一个构造方法 this.name = name; System.out.println(this.name); } public Book(String name,double price){ this.name = name; this.price = price; System.out.println("name:"+this.name+" price:"+this.price); } } public class Test { public static void main(String[] args) { //传递一个参数调用带有一个参数的构造方法,实例化一个对象 Book book = new Book("富婆通讯录"); //创建对象需要调用合适的构造方法 //传递两参数调用带有两个参数的构造方法 Book book1 = new Book("富婆通讯录",198.9); } }
构造方法不能有返回值
注意事项
实例化一个对象要调用合适的构造方法
实例化对象时通过传递不同参数列表,调用不同的构造方法
构造方法方法名与类名相同
构造方法无返回值
构造方法可以有多个,参数列表不同构成了方法的重载
static关键字
我们之前学过static修饰的方法!
修饰属性
修饰方法
修饰代码块
修饰类
修饰属性
static修饰属性,该属性属于类,不属于对象,通过类可以调用该属性!该属性只要一分,就是一个类的所有实例对象共用该static属性!
class People1{ //static修饰属性,该属性属于类 public static String name; public static int age; } public class Test { public static void main(String[] args) { //通过类名调用类属性,并且赋值 People1.name = "bug郭"; People1.age =18; //实例化一个对象 People1 people1 = new People1(); //通过对象调用(static修饰的)类属性, // 不建议这样使用,类属性属于类,应该通过类名调用 System.out.println("name:"+people1.name); System.out.println("age:"+people1.age); } }
类的实例化对象共用类属性
当我们创建多个对象分别调用他们的类方法时,运行结果如下:
可以看到static修饰的类属性,空间只有一块,属于所有的对象,当我们改变了类属性,所有的对象的属性也跟着改变!就是说public static int age; 赋值18后,所有的People1对象都是18岁!
可以看到static修饰的类属性,只有一份,在方法区中!
修饰方法
static修饰方法和修饰属性相同!属于类方法,只有一份!
class People1{ public static String name; public static int age; public static void eat(){ System.out.println("eat"); } } public class Test { public static void main(String[] args) { People1.eat(); //通过类名调用 People1 people1 = new People1(); people1.eat(); //实例对象调用 } }
通过static修饰的方法,进行调用时可以直接通过类名.方法调用访问!并且和类变量一样不建议使用对象调用!
static修饰的方法只能调用static修饰的成员 class Animal{ String name; int age1; //未被static修饰,实例化变量属于对象 static int age2; //static修饰,类对象,属于类 public static void eat(){ this.age1 = 12; //error 实例化成员不能在static修饰的类方法中使用 age2 = 12; //staic方法只允许使用该方法外类中中的static修饰的成员 } }
this和super不能对类成员进行访问
class Animal{ String name; static int age2; //static修饰,类对象,属于类 public static void eat(){ this.age2; //error // 类变量(static修饰)不能用this和super访问,他们都代表对象的引用 } }
注意事项
静态方法和实例无关,而是和类相关。 因此这导致了两个情况:
静态方法不能直接使用非静态数据成员或调用非静态方法(非静态数据成员和方法都是和实例相关的)。
this和super两个关键字不能在静态上下文中使用(this 是当前实例的引用, super是当前实例父类实例的引用, 也是和当前实例相关)。
main 方法为static方法。
总结
class Person { public int age;//实例变量,存放在对象内 public String name;//实例变量 public String sex;//实例变量 public static int count;//类变量也叫静态变量,编译时已经产生,属于类本身,且只有一份。存放在方法区 public final int SIZE = 10;//被final修饰的叫常量,也属于对象。 被final修饰,后续不可更改 public static final int COUNT = 99;//静态的常量,属于类本身,只有一份 被final修饰,后续不可更 //实例成员函数 public void eat() { int a = 10;//局部变量 System.out.println("eat()!"); } //实例成员函数 public void sleep() { System.out.println("sleep()!"); } //静态成员函数 public static void staticTest(){ //不能访问非静态成员 //sex = "man"; error System.out.println("StaticTest()"); } } public class Test{ public static void main(String[] args) { //产生对象 实例化对象 Person person = new Person();//person为对象的引用 System.out.println(person.age);//默认值为0 System.out.println(person.name);//默认值为null //System.out.println(person.count);//会有警告! //正确访问方式: System.out.println(Person.count); System.out.println(Person.COUNT); Person.staticTest(); //总结:所有被static所修饰的方法或者属性,全部不依赖于对象。 person.eat(); person.sleep(); } }