这一节我们来到了类与对象,这是Java的一大特色,需要重点掌握。
目录
一、面向对象含义
说到面向对象,就要说到面向过程。
C语言就是经典的面向过程语言,而Java是经典的面向对象语言。
面向过程注重的是过程,在整个过程中所涉及的行为,就是功能。
面向对象注重的是对象,也就是参与过程所涉及到的主体。是通过逻辑将一个个功能实现连接起来。
面向对象编程步骤:找对象,建对象,用对象。
二、普通类
让我们看一段普通类的定义:
class Person{
//成员变量
public String name;
public int age;
//方法
public void eat(){
System.out.println(name + "正在吃饭");
}
public void sleep(){
System.out.println(name + "正在睡觉");
}
}
class就是类,是一个引用类型,类中可以包含成员变量与成员方法等。
类的实例化
每个类都能实例化,实例化也就是创建对象。
类就像是一个模板,模板就需要实例化
我们可以通过new来创建对象。
因为是模板,所以要去初始化他们的值。
不初始化,字符串默认null,整数默认0
public static void main(String[] args) {
//通过new来实例化对象
Person person = new Person();//每个对象都有自己的空间
//person是一个变量,里面存放着地址,通过地址在堆内找到对应内存
Person person1 = new Person();
person.name = "gaobo";
System.out.println(person.name);
System.out.println(person1.name);//null
System.out.println(person.age);//0
person.eat();
person1.sleep();
}
三、static关键字
这里来探讨含static修饰的变量或方法。
static很简单,记住关键点:静态的变量或方法是属于类的,不属于对象。
class Stu{
//静态成员变量也叫类变量,在方法区存储
//这个变量是类的,不是对象的
public static int age;
public static void staticFunc(){
System.out.println("一个静态方法");
}
}
public static void main(String[] args) {
Stu a = new Stu();
a.age++;
Stu.age++;
}
这里的a.age++是正确的,但是没必要,因为age是静态的,属于类的,不属于对象。
如果再new一个对象
public static void main(String[] args) {
Stu.age = 0;//初始化
Stu a = new Stu();
a.age++;
System.out.println(a.age);//1
Stu a1 = new Stu();
a1.age++;
System.out.println(a1.age);//2
}
这里的age是静态的,属于类,所以age是两个对象公用的。
在内存中,如图:
堆中只会存放普通的变量与方法,静态的都存放在方法区中。
对于静态方法与变量有些注意点:
class Stu{
public int id;
public static void staticFunc(){
//静态方法内不能访问非静态变量
//id = 1;
//也不能调用普通方法
//eat();
System.out.println("一个静态方法");
}
public void eat(){
//普通方法内不能创建静态变量,因为在方法内部是局部变量
//static int id = 1;
//但是可以调用静态方法
staticFunc();
}
}
当然这里不用强记,因为编译器会帮你报错的。
四、封装
封装是面向对象一个很重要的特点。
我们在写代码中,有时不必知道类的实现,只要知道怎么用就行。
之前注意到有一个关键字是public,即公共的。
所以这里有对应的private,即私有的。
class Tea{
private String name;
private int age;
}
这样就是两个封装后的私有方法。
一旦被private修饰,任何对象都不能访问到,那么我们怎么修改呢?
可以使用getter和setter方法。
class Tea{
private String name;
private int age;
//get和set方法来赋值与获取
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
这里的this也代表引用,就是调用本类里面的变量,来区别于方法的局部变量。
在main函数内:
public static void main3(String[] args) {
Tea tea = new Tea();
tea.setAge(18);
tea.setName("zjk");
}
五、构造方法
说到构造方法,就要说到new的执行过程。
1、为对象分配内存空间
2、调用对象的构造方法
再注意下构造方法的规则:
1.方法名称必须与类名称相同
2.构造方法没有返回值类型声明
3.每一个类中一定至少存在一个构造方法(没有明确定义,则系统自动生成一个无参构造)
示例:
class Peop{
public Peop()
System.out.println("无参的构造方法");
}
}
public class TestDemo {
public static void (String[] args) {
Peop peop = new Peop();
}
}
这里就创建了一个无参的构造方法,在创建对象时,会自动调用这个构造方法。
构造方法也可以重载,如下:
class Peop{
//构造方法是用来创建对象的
public String name;
public int age;
public Peop(){
System.out.println("无参的构造方法");
}
public Peop(int age){
this.age = age;//this代表当前对象的引用
System.out.println("带一个参");
}
public Peop(String name, int age){
this.age = age;
this.name = name;
System.out.println("带二个参");
}
}
上面代码就实现了构造方法的重载。
那么在创建对象时也有区别:
public class TestDemo {
public static void main4(String[] args) {
Peop peop = new Peop();
Peop peop1 = new Peop(18);
Peop peop2 = new Peop("zjk", 18);
}
}
this关键字
前面看了this的两种用法,分别借助this来访问对象的字段和方法
这里和构造方法结合起来:
class Peop{
//构造方法是用来创建对象的
public String name;
public int age;
public Peop(int age){
this.age = age;//this代表当前对象的引用
System.out.println("带一个参");
}
public Peop(String name, int age){
this.age = age;
this.name = name;
System.out.println("带二个参");
}
public Peop(){
this(18);//指的是调用含age的构造方法,只能在构造方法中
//this("zjk", 18);this()必须要放第一个
System.out.println("无参的构造方法");
}
}
注意看这里的Peop(),这个构造方法通过this调用了两个另外的构造方法。
但是要注意,this调用构造方法这种做法,这个this必须要放在第一个。
六、代码块
最后,我们来讨论一下代码块。
代码块很简单,就是使用 {} 定义的一段代码.
根据代码块定义的位置以及关键字,又可分为以下四种:
普通代码块、构造块、静态块、同步代码块
第一种是普通代码块,这种很简单,基本不用。
public class Main{
public static void main(String[] args) {
{ //直接使用{}定义,普通方法块
int x = 10 ;
System.out.println("x1 = " +x);
}
int x = 100 ;
System.out.println("x2 = " +x);
}
}
第二种是构造块,就是在类中定义的普通代码块
class Map{
//构造块
{
System.out.println("实例代码块");
}
}
第三种是静态块,即用static修饰普通代码块
class Map{
static {//静态代码块
public static int age = 10;
//静态代码块只能赋值静态的变量
System.out.println("静态代码块");
age = 99;
}
}
如果我们让构造块和静态块同时出现在类中,执行顺序如何?
class Map{
//代码块优先调用,静态代码块最优
{
System.out.println("实例代码块");
}
static {//静态代码块,不用实例化就可以执行,但是main函数要有内容,且只会执行一次
//静态代码块只能赋值静态的变量
System.out.println("静态代码块");
age = 99;
}
public static int age = 10;//age的值与创建顺序有关,但未初始化优先看static内
}
public static void main(String[] args) {
Map map = new Map();
System.out.println(Map.age);
Map map1 = new Map();//第二次静态代码块不执行,只执行一次
}
总结一下要点:
1、代码块优先调用,静态代码块最优
2、静态代码块,不用实例化就可以执行,但是main函数要有内容,且只会执行一次
3、静态代码块内只能赋值静态的变量
4、第二次实例化对象,静态代码块不执行,只执行一次
🦀🦀👉👍