java中的类和对象

类和对象

一、OOP特征

1.抽象
抽象是指只关心我所要的,不关注我不需要的,比如我想设计一个用户订单管理系统,那么我需要知道订单号,用户信息等等,但是我不需要知道用户是否结婚,有几个兄弟姐妹等等。

2.封装
封装是把过程和数据包围起来,对数据的访问只能通过指定的方式。

3.继承
新的类继承了原始类后,新类就继承了原始类的特性,新类称为原始类的子类(派生类),原始类就是父类(基类),子类会继承父类的方法和实例变量,并且子类可以修改这些方法或者新增新的方法。

4.多态
多态是指,继承于同一个父类的若干个子类,可以各自重写父类中原来的方法而不互相影响。

public class Main {
    public static void main(String[] args) {
        new Teacher().say();
        new Student().say();
    }
}
class Person{
	public void say() {
		
	}
}
class Teacher extends Person{
	public void say() {
		System.out.println("安静");
	}
}
class Student extends Person{
	public void say() {
		System.out.println("NO");
	}
}

输出结果为
安静
NO

二、类和对象的关系

类是抽象的数据类型,不能代表具体事物,比如动物,植物,电子产品等等,这些都是抽象的概念,对象是抽象概念的实例,比如我就是人的一个具体事例

三、对象和引用的关系

引用指向对象,因为创建出对象后,不方便直接使用,所以就需要一个引用类型的变量去接收这个对象。

四、方法的定义和使用

方法的定义模板: 修饰符 返回类型 方法名(参数列表) 异常抛出类型{

}
修饰符:
public static abstract final等等都是修饰符,一个方法可以有多个修饰符。修饰符之间没有先后顺序之分。

返回类型:
方法执行完如果需要返回数据,那么必须在方法的定义的时候声明返回值的类型,如果没有返回值,那么返回类型就要写void。构造方法不需要写返回类型

方法名:
一般方法名小写,采用驼峰命名法

参数列表:
可以没有,也可以有多个参数

异常抛出类型:
如果方法中的代码在执行过程中,可能会出现一些异常情况,那么就可以在方法上把这些异常声明并抛出,也可以同时声明抛出多个异常,使用逗号隔开即可。

方法的调用:

方法定义后不会被立刻执行,只有被调用的时候才会执行。

1.静态方法
使用static修饰符修饰的方法就是静态方法,该方法可以通过类来调用也可以通过对象调用,一般推荐使用类来调用,因为静态方法属于类。

2.非静态方法
没有使用static修饰符修饰的方法就是非静态方法,调用这种方法一定要通过对象去调用,因为非静态方法属于对象。

3.类之间方法的调用
假设一个类中有两个方法a,b
假如ab都非静态方法,那么两者之间可以相互调用
假如ab都是静态方法,两者之间也可以相互调用
假如ab中有一个是静态方法,一个是非静态方法,那么静态方法不可以调用非静态方法,非静态方法可以调用静态方法。
因为静态方法是属于类的,类是先被加载的,非静态方法属于对象,所以静态方法无法调用非静态方法。
4.调用方法的传参(参见 值传递和引用传递)

五、this关键字

1.区分全局变量和局部变量

public class Main {
	private String name = "tom";
    public static void main(String[] args) {
        new Main().test("jack");
    }
    public void test(String name) {
    	System.out.println(name);
    	System.out.println(this.name);
    }
}

输出结果为
jack
tom

2.调用类中的其它方法

public class Main {
	private String name = "tom";
    public static void main(String[] args) {
        new Main().test2();
    }
    public void test(String name) {
    	System.out.println(name);
    	System.out.println(this.name);
    }
    public void test2() {
    	this.test("jack");
    }
}

输出结果为
jack
tom

3.调用类中的其他构造器

public class Main {
	private String name;
    public static void main(String[] args) {
        System.out.println(new Main().name);
    }
   public Main() {
	   this("tom");
   }
   public Main(String name) {
	   this.name=name;
   }
}

输出结果
tom
this的这种用法只能在构造器中使用,而且必须在构造器的第一句。

4.this关键字在类中的意义
其实this关键字在类中表示的就是当前类将来创建出的对象。

public class Main {
	public Main(){
		System.out.println("this:"+this);
	}
    public static void main(String[] args) {
        System.out.println("Main:"+new Main());
    }
}

输出结果为
this:test.Main@15db9742
Main:test.Main@15db9742
显然两个打印结果一样,这样就很好的解释了上面三种this的使用方式了。注意:类是模板,模板中写的this并不是只有一个,每个对象中都有一个属于自己的this。

六、方法的重载

类中有许多方法,方法名相同,但是方法的参数各不相同,这种就叫做方法的重载。
方法重载的条件:
方法名相同
参数列表不同
方法的返回值类型可以不同
注意:判断一个类中两个方法是否一样,主要看方法名和参数列表

七、创建和初始化对象

1.为对象分配内存空间,将对象的全局变量自动初始化赋值
2.如果全局变量有显示赋值的,那么将之前的默认值覆盖
3.调用构造器
4.把对象内存地址赋值给变量

构造器

特点:
1.必须和类的名字相同
2.不能有返回值,也不能写void

作用:
1.通过new关键字创建对象的时候需要使用构造器
2.为对象中的属性初始化赋值

重载:
构造器可以重载,默认的是无参构造器,但是也可以自己写若干个有参构造器,一旦自己写了有参构造器,原本的无参构造器就会被覆盖掉,如果后面需要使用无参构造器,那么需要自己重新写一个。

构造器之间的调用:
通过上述的this关键字,构造器之间可以相互调用,这种相互调用只是调用代码,不会产生新的对象。

八、继承

1.继承是类和类之间的一种关系

2.继承关系的两个类一个为子类,一个为父类,子类继承父类,通过关键字extends实现。

3.子类和父类之间有 is a 的关系,子类 is a 父类

4.类与类之间的继承是单继承,子类只能直接继承一个父类,但是父类可以有多个子类。

5.父类中的属性和方法可以被子类继承
但是能不能使用,需要看属性和方法的修饰符。父类中的构造器是不能被子类继承的,但是子类的构造器中,会隐式的调用父类中的无参构造器(默认使用super关键字)。

6.Object类
java中每一个类都直接或者间接继承自Object类。在Object类中,提供了一些方法被子类继承,那么就意味着,在java中,任何一个对象都可以调用这些被继承过来的方法。

九、super关键字

子类继承父类后,在子类中可以使用this来表示访问或调用子类中的属性或方法,使用super就表示访问或调用父类中的属性和方法。

1.访问父类的属性

public class Main {
    public static void main(String[] args) {
    	new Teacher().test();
    }
}
class Person{
	String name = "tom";
}
class Teacher extends Person{
	String name = "jack";
	public void test() {
		System.out.println(name);
		System.out.println(this.name);
		System.out.println(super.name);
	}
}

输出结果
jack
jack
tom

2.调用父类中的方法

public class Main {
    public static void main(String[] args) {
    	new Teacher().test();
    }
}
class Person{
	public void say() {
		System.out.println("Person");
	}
}
class Teacher extends Person{
	public void say() {
		System.out.println("Teacher");
	}
	public void test() {
		say();
		this.say();
		super.say();
	}
}

结果为
Teacher
Teacher
Person

3.调用父类中的构造器
子类构造器中会隐式的调用父类的无参构造器。

public class Person{
			
		}
		public class Student extends Person{
			//编译通过,子类构造器中会隐式的调用父类的无参构造器
			//super();
			public Student(){

			}
		}

如果父类中的无参构造器被覆盖了,那么编译会报错,必须在父类中添加一个父类的无参构造器。

public class Person{
			protected String name;
			public Person(String name){
				this.name = name;
			}
		}
		public class Student extends Person{
			//编译报错,子类构造器中会隐式的调用父类的无参构造器,但是父类中没有无参构造器
			//super();
			public Student(){

			}
		}

子类构造器也可以显示的调用父类的有参构造器。

public class Person{
			protected String name;
			public Person(String name){
				this.name = name;
			}
		}
		public class Student extends Person{
			//编译通过
			public Student(){
				super("tom");
			}
		}

注:不管是显式还是隐式的父类的构造器,super语句一定要出现在子类构造器中第一行代码。所以this和super不可能同时使用其调用构造器的功能,因为它们都要出现在第一行代码位置。

十、方法的重写

1.方法重写只存在于子类和父类(包括直接父类和间接父类)之间。在同一个类中方法只能被重载,不能被重写。
2.静态方法不能被重写
(1)父类的静态方法不能被子类重写成非静态方法
(2)父类的非静态方法不能被子类重写成静态方法
(3)子类可以定义与父类的静态方法名相同的静态方法,但是这个不是重写
3.私有方法不能被子类重写
因为子类继承父类后无法访问私有方法
4.重写的语法
(1)方法名必须相同
(2)参数列表必须相同
(3)访问控制修饰符不能被缩小,可以扩大也可以一样
(4)异常抛出类型可以被缩小,但是不能扩大
(5)返回类型可以一样也可以不一样,如果不一样那么重写后的方法返回的类型必须是重写前方法返回类型的子类型

十一、多态

相同类的不同子类,调用相同的方法,结果是不同的。

public class Main {
    public static void main(String[] args) {
        new Teacher().say();
        new Student().say();
    }
}
class Person{
	public void say() {
		
	}
}
class Teacher extends Person{
	public void say() {
		System.out.println("安静");
	}
}
class Student extends Person{
	public void say() {
		System.out.println("NO");
	}
}

输出结果为
安静
NO

1.一个对象的实际类型是确定的

2.可以指向这个对象的引用类型有很多
例如Teacher继承自Person类,那么
Person t = new Teacher();
Teacher t = new Teacher();
Object t = new Teacher();
因为Person和Object都是Teacher的父类型。
即:一个对象的实际类型是确定,但是可以指向这个对象的引用的类型,却是可以是这对象实际类型的任意父类型。

3.一个父类型的引用可以指向任意一个子类的对象
Person p = null;
p = new Student();
p = new Teacher();
p = new Person();

4.多态中的方法调用
子类继承父类,调用a方法,如果a方法在子类中没有重写,那么就是调用的是子类继承父类的a方法,如果重写了,那么调用的就是重写之后的方法。

5.子类中独有方法的调用

public class Main {
    public static void main(String[] args) {
    	Person p = new Teacher();
    	p.run();
    }
}
class Person{
	public void say() {
		System.out.println("Person");
	}
}
class Teacher extends Person{
	public void say() {
		System.out.println("Teacher");
	}
	public void run() {
		System.out.println("Running");
	}
}

编译会出错,因为编译器检查变量p的类型是Person,但是在Person类中并没有发现test方法,所以编译报错.
注:一个变量x,调用一个方法test,编译器是否能让其编译通过,主要是看声明变量x的类型中有没有定义test方法,如果有则编译通过,如果没有则编译报错.而不是看x所指向的对象中有没有test方法.

6.子类引用和父类引用指向对象的区别
子类引用可以调用子类对象中的方法,父类引用只能调用父类对象中的方法。
但是父类引用可以指向父类对象以及父类的所有子类对象。

7.重写、重载和多态的关系
重载是编译时多态
调用重载的方法,在编译期间就要确定调用的方法是谁,如果不能确定则编译报错
重写是运行时多态
调用重写的方法,在运行期间才能确定这个方法到底是哪个对象中的。这个取决于调用方法的引用,在运行期间所指向的对象是谁,这个引用指向哪个对象那么调用的就是哪个对象中的方法。(java中的方法调用,是运行时动态和对象绑定的)

8.instanceof和类型转换

System.out.println(x instanceof Y);
代码能否编译通过。主要看声明变量x的类型是否和Y存在子父类关系,无论x是Y的子类还是父类。
输出的结果是true还是false,主要看x的实际指向的对象,是否是Y的子类,如果是Y的子类,那么结果为true,否则为false

类型转换
上文已经提到过,声明的变量类型如果是父类的那么无法调用子类中特有的方法,这个时候就需要类型转换,
Person p = new Student();
Student s = (Student)p;
s.run();

X x = (X)o;
强制类型转换运行是否报错,主要看o变量所指向的实际类型,与X是否存在子父类关系,如果存在,那么运行正常,反之,那么运行会报错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值