文章目录
什么是面向对象
-
对于描述复杂的事物,为了从宏观上把握,从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
-
面向对象的本质就是:以类的方式组织代码,以对象的方式来组织数据
-
三大特征:
- 封装
- 继承
- 多态
类与对象的创建
-
类是一种抽象的数据类型,它是对某一类事物整体描述、定义,但是并不能代表某一个具体的事物
-
对象就是抽象概念的具体事例
-
使用new关键字创建对象
public class Student {
//属性:字段
String name;
int age;
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
//一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
//类:抽象的,实例化
//类实例化后会返回一个自己的对象
//student对象就是Student类的具体实例
Student xiaoming = new Student();
Student xiaohong= new Student();
xiaoming.name="xiaoming";
xiaoming.age=23;
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
}
}
构造器
- 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
- 类中的构造器也成为构造方法,是进行创建对象的时候必须要调用的。并且构造器有以下俩个特点:
1. 必须和类的名字相同
2. 必须没用返回值,也不能写void
反编译查看一个空类
一个类即使什么都不写,也会存在一个构造方法
有参构造:一旦定义了有参构造,无参就必须显示定义
public class Person {
String name;
//实例化初始值
public Person(){ //alt+insert 快捷生成构造器
this.name="xiaoming";
}
//有参构造
public Person(String name){
this.name=name;
}
}
- 使用new关键字,本质是在调用构造器
- 用来初始值
public static void main(String[] args) {
//new 实例化了一个对象
Person person = new Person("小明 ");
System.out.println(person.name);
}
创建对象内存分析
public class Pet {
public String name;
public int age;
public void shout(){
System.out.println("叫");
}
}
public class Application {
public static void main(String[] args) {
//new 实例化了一个对象
Pet dog=new Pet();
dog.name="旺财";
dog.age=3;
dog.shout();
System.out.println(dog.age);
System.out.println(dog.name);
}
}
封装
- 我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉:低耦合:仅暴露少量的方法给外部使用。
- 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
- Java中类只有单继承没有多继承
public class Student {
// public–都可访问
// protected–包内和子类可访问
// 不写(default)–包内可访问
// private–类内可访问
private String name;
private char sno;
private char sex;
private int age;
//get 快捷键alt+insert自动生存get/set
public String getName() {
return name;
}
public char getSno() {
return sno;
}
public char getSex() {
return sex;
}
// set
public void setName(String name) {
this.name = name;
}
public void setSno(char sno) {
this.sno = sno;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age<0||age>120)
this.age=3;
else
this.age = age;
}
}
public class Application {
public static void main(String[] args) {
Student s1=new Student();
s1.setAge(-1);//不合法的
System.out.println(s1.getAge());
}
}
- 封装可以提高程序安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 增加系统的可维护性
继承
extends的意识是“拓展”,子类是父类的拓展
//父类
public class Person {
private int money=1000000;
public void say(){
System.out.println("说了一句话");
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
public class Student extends Person{
}
public class Application {
public static void main(String[] args) {
Student student=new Student();
student.say();
System.out.println(student.getMoney());
}
}
在Java中,所有的类,都默认直接或者间接继承object类
super
注意:
1. super调用父类的构造方法,必须在构造方法的第一个
2. super必须只能出现在子类的方法或者构造方法中
3. super和this不能同时调用构造方法
super与this 的区别
代表的对象不同:
this:本身调用者这个对象
super:代表父类对象的应用
前提
this;没有继承也能使用
super:只能在继承条件才可以使用
构造方法
this:本类的构造
super:父类的构造
public class Person {
//私有的无法被继承
public Person(){
System.out.println("父类无参构造执行");
}
protected String name="xiaoming";
public void print(){
System.out.println("Person");
}
}
//子类
public class Student extends Person{
private String name="xiaohong";
public Student() {
//隐藏代码:调用了父类的无参构造
super();//调用父类的构造器必须要在子类构造器的第一行
System.out.println("子类无参构造执行");
}
public void print(){
System.out.println("Student");
}
public void test(String name){
System.out.println(name);//xiao111
System.out.println(this.name);//xiaohong
System.out.println(super.name);//xiaoming
}
public void test(){
print();//Student
this.print();//Student
super.print();//Person
}
}
public class Application {
public static void main(String[] args) {
Student Student =new Student();
Student.test();
}
}
方法的重写
重写:需要有继承关系,子类重写父类的方法
1. 方法名必须相同
2. 参数列表列表必须相同
3. 修饰符:范围可以扩大但不能缩小 public>protected>default>private
4. 抛出的异常:范围,可以被缩小,但不能扩大
重写,子类的方法和父类必要一致,方法体不同
为什么要重写:
1. 父类的功能,子类不一定需要,或者不一定满足
//重写都是方法的重写,与属性无关
public class B {
public void test(){
System.out.println("b.test()");
}
}
public class A extends B{
//overside 重写
@Override //注释:有功能的注释
public void test() {
System.out.println("a.test");;
}
}
public class Application {
public static void main(String[] args) {
//方法的调用只和左边,定义的数据类型有关
A a=new A();
a.test();//A
//父类的引用指向了子类
B b=new A();//子类重写了父类的方法
b.test();//B
//静态方法与非静态方法区别很大
}
}
多态
- 即同一方法可以根据发送对象的不同而采用多种不同的行为方式
- 一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
对象能执行的方法,主要看对象左边的类型,和右边关系不大
子类重写了父类的方法,执行子类的方法,否则执行父类方法
public class Person {
public void run(){
System.out.println("run");
}
}
public class Student extends Person {
@Override
public void run() {
System.out.println("son");;
}
public void eat(){
System.out.println("eat");
}
}
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//可以指向的引用类型就不确定了
//Student 能调用的方法都是自己的或者继承父类的
Student s1=new Student();
//Person父类,可以指向子类,但是不能调用子类独有的方法
Person s2=new Student();
Object s3=new Student();
s2.run();//子类重写了父类的方法,执行子类的方法
s1.run();
//**对象能执行的方法,主要看对象左边的类型,和右边关系不大**
((Student) s2).eat();
}
}
注意:
- 多态是方法的多态,属性没有多态
- 父类和子类,有联系才能转化 转换异常 classcastException
- 存在条件:继承关系,方法需要重写,父类引用指向子类对象 father f1=new son();
无法重写的:
1. static 方法属于类的,不属于实例
2. final常亮;
3. private方法
instanceof与类型转换
instanceof判断两个类之间有没有父子关系,有为true没有为false
public class Application {
public static void main(String[] args) {
Object object = new Student();
//System.out.println(x instanceof y);
//编译能不能通过,取决于x与y有没有关系
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
Person person =new Student();
}
}
类型转换:
public class Application {
public static void main(String[] args) {
//类型之间的转换:父 子
//高 低
Person person=new Student();
//student将这个对象转换为student类型,我们就可以使用student类型的方法
// 子类转换为父类,可能丢失一些方法
Student student=new Student();
student.go();
((Student)person).go();
}
}
总结:
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型;
- 把父类转换为子类,向下转型需要强制转化
- 方便方法的调用,减少重复的代码
static
public class Student {
private static int age; //静态变量
private double score; //非静态变量
public void run(){
}
public static void go(){
}
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);
System.out.println(s1.age);
System.out.println(s1.score);
}
}
static修饰的属性方法跟类一起加载,不需要创建对象也能调用
代码块:
public class Person {
{
//代码块(匿名代码块)
System.out.println("匿名代码块");
}
static {
//静态代码块
System.out.println("静态代码块");
}
public Person() {
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("==========");
Person person2 =new Person();
}
}
静态代码块
匿名代码块
构造方法
==========
匿名代码块
构造方法
静态代码块只加载一次
public class Test {
public static void main(String[] args) {
System.out.println(Math.random());
}
}
也可以静态导入包,从而直接用random
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
System.out.println(random());
}
}
抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法,修饰类就是抽象类
- 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类
- 抽象类不能用new关键字创建对象,它是用来让子类继承的
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要被声明为抽象类
//abstract 抽象类
public abstract class Action {
//约束~交给别人实现
//abstract,抽象方法,只有方法的名字,没有方法的实现
public abstract void doSomeThing();
//抽象类中可以写普通方法,抽象方法必须在抽象类中
}
//抽象类的所有方法,继承了它的子类,都必须要实现它的方法
//除非子类也是抽象类
public class A extends Action{
@Override
public void doSomeThing() {
}
}
接口的定于与实现
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有
接口:只有规范,自己无法写方法,约束和实现分离
//interface 定义的关键字,接口都需要有实现类
public interface UserService {
//接口中的所有定义都是抽象的 ,自带public abstract
void run(String name);
void delete(String name);
void update(String name);
void select(String name);
}
//类可以实现接口 implement
//实现了接口的类,就需要重写接口中的方法
public class UsetServiceImpl implements UserService,TimeService{
//alr+insert快捷键
@Override
public void time() {
}
@Override
public void run(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void select(String name) {
}
}
public interface TimeService {
void time();
}
- 接口内的方法自带public abstract 属性自带public static final
- implement可以实现多个接口
- 必须重新接口中的方法
内部类
成员内部类
public class Outer {
private int id=10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性
public void getId(){
System.out.println(id);
}
}
}
//一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getId();
}
}
这是内部类的方法
10
静态内部类
加个static修饰词就能变成静态内部类
public static class Inner
写在public class下面的类
public class Outer {
}
//一个java类中可以有多个class文件,但只能有一个public class
class A{
}
局部内部类
public class Outer {
//局部内部类
public void method(){
class Inner{
public void in(){
}
}
}
}
匿名内部类
public class Text {
public static void main(String[] args) {
//没有名字初始化类,不用将实例保存到变量动
new Apple().eat();
new UserService(){
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserService{
void hello();
}