1.初识面向对象
1.java核心就是面向对象编程
oop----面向对象编程
oo----面向对象
2.面向过程思想:步骤清晰简单,第一步做什么,第二步做什么…
面向过程适合处理一些较为简单的问题。
面向对象思想:物以类聚,分类的思维,首先解决问题需要哪些分类,
然后对这些分类进行单独思考,
最后才对某个分类下的细节 进行面向过程的思索。
面向对象适合处理复杂的问题,适合处理需要多人协作的问题。
3.面向对象与面向过程不可分割
面向对象-----框架
面向过程-----具体实施
4.oop的本质就是:以类的方法组织代码,以对象的形式封装数据
5.oop的三大特性:封装,继承(子类,父类),多态
6.从认识论的角度考虑是先有对象后有类。对象是具体的事物,类是抽象的,是对对象的抽象。
从代码运行角度考虑是先有类后有对象。类是对象的模板。
2.类和对象的创建
1.定义:
类是一种抽象的数据类型,它是对某一类事物整体的描述,并不代表某一具体的事物。
对象是抽象概念的具体实例。
2.new关键字创建对象
//以后不要在每一个类里都加上main方法了
public class Demo01 {
//属性:字段
String name; //默认值null
int age; //默认值0
//方法
public void study(){
System.out.println(this.name+"在学习");
}
}
/*
//一个项目应该只存在一个main方法,测试类
public class Application {
public static void main(String[] args) {
//类的实例化
//类实例化后会产生一个自己的对象!
//Demo01类的对象是xiao
Demo01 xiao = new Demo01();
xiao.name = "小明";
xiao.age = 6;
System.out.println(xiao.name);
System.out.println(xiao.age);
}
}
*/
3.构造器
1.无参构造器
public class Person {
//一个类即使什么都不写,它也会存在一个方法
String name;
//显示构造器,无参构造器
// 所以说构造器的作用是实例化初始值
//使用new关键字本质上是在调用构造器
public Person(){
this.name = "小明";
}
}
public class Application {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name); //小明
}
}
2.有参构造器
public class Person {
String name;
public Person(){}
//有参构造器:一旦定义了有参构造器,还要使用无参构造的话,就要无参构造器必须显式定义,否则无效
public Person(String name) {
this.name = name;
}
public class Application {
public static void main(String[] args) {
Person person = new Person("xiao");
System.out.println(person.name); //xiao
}
}
另外:快捷键Alt+Insert生成构造器
3.特点
构造器首先方法名和类名相同,其次没有返回值
4.内存分析
附代码如下:
public class Pet {
public String name;
public int age;
public void shout() {
System.out.println("叫了一声");
}
}
public class Application {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "汪";
dog.age = 1;
dog.shout();
System.out.println(dog.age);
System.out.println(dog.name);
Pet cat = new Pet();
}
}
5.封装(get,set)
1.我们程序设计追求**”高内聚,低耦合“**:
高内聚是指类的内部数据操作细节自己完成,不许外部干涉;
低耦合是指仅暴露少量方法给外部使用。
对于代码来说:属性私有 get/set
快捷键:Alt+Insert 自动生成get,set
public class Student {
//属性私有,外部无法调用
private String name;
private int id;
private char sex;
private int age;
//提供能够操作这些属性的方法!
//提供一些public的get,set方法
//get获得这个属性
public String getName(){
return this.name;
}
//set给这个属性赋值
public void setName(String name){
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 100 || age < 0) {
this.age = 3;
}else{
this.age = age;
}
}
}
public class Application {
public static void main(String[] args) {
Student s = new Student();
s.setName("x");
System.out.println(s.getName()); //x
s.setAge(999);
System.out.println(s.getAge()); //3
}
}
2.封装的好处
1.提高程序安全性,保护数据
2.隐藏代码实现细节
3.统一接口:get,set(可进行安全性检测)
4.系统可维护性增加了
6.继承
1.继承的本质是对某一批类的抽象,继承是类与类之间的一种关系,除此之外,类和类之间还有依赖、组合·、聚合·等。继承关系的两个类,一个为子类(派生类),一个为父类(基类),子类继承父类,使用关键字extends来表示。
2.java中只有单继承,没有多继承(接口可以多继承)。(一个儿子只可以有一个爸爸,一个爸爸可以有多个儿子)
3.在java中所有的类都默认直接或者间接继承object类。(ctrl+h查看继承关系)
//父类People
package oop.Demo02;
public class People {
public int money = 10_0000_0000;
public void say(){
System.out.println("说了一句话");
}
}
//子类 学生 is 人
package oop.Demo02;
public class Student1 extends People{
}
//测试类
package oop;
import oop.Demo02.Student1;
//一个项目应该只存在一个main方法,测试类
public class Application {
public static void main(String[] args) {
Student1 student = new Student1();
student.say();
System.out.println(student.money);
}
}
/*四个优先级
public
protected
default
private
*/
7.Super(调用父类)
1.注意点:
1.super调用父类的构造方法,必须在构造方法的第一个
2.super必须只能出现在子类的方法或者构造方法中
3.super和this不能同时调用构造方法
2. super VS this:
带表对象不同:
this本身调用者这个对象
super代表父类对象的应用
前提不一样:
this:没有继承也可以使用
super:只能在继承条件下使用
构造方法:
this():本类的构造
super():父类的构造
//父类
package oop.Super;
public class Demo03 {
public Demo03() {
System.out.println("父类的无参构造执行了");
}
//私有的(private)东西无法被继承
protected String name = "小明";
public void print(){
System.out.println("java");
}
}
//子类
package oop.Super;
public class Demo04 extends Demo03 {
public Demo04() {
//隐藏代码调用了父类的无参构造器
super();//可以不写,调用父类的构造器,必须在子类的第一行
System.out.println("子类的无参构造执行了");
}
private String name = "小红";
public void print(){
System.out.println("jav");
}
public void text1(){
print();
this.print();
super.print();
}
public void text(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}
//测试类
package oop;
import oop.Super.Demo04;
//一个项目应该只存在一个main方法,测试类
public class Application {
public static void main(String[] args) {
Demo04 s = new Demo04();
s.text("xiao");
s.text1();
}
}
运行结果:
8.方法重写(Override)
1.注意点:
1.重写需要有继承关系,子类重写父类的方法
2.重写都是方法的重写,和属性无关
3.方法名必须相同,参数列表也必须相同,方法体不同
4.重写只和非静态方法有关
5.修饰符范围从父类到子类可以扩大,public>protected>default(默认)>private
6.重写快捷键Alt+Insert
@Override//注解:有功能的注释
7.重写可能会抛出异常:范围可以被缩小,但不可以扩大(父类欠100,子类欠1000就会抛出异常)。
2.重写在有无static的区别
1.静态方法时
//父类
package oop;
public class B {
public static void test(){
System.out.println("B-test()");
}
}
//子类
package oop;
public class A extends B {
public static void test(){
System.out.println("A-test()");
}
}
//测试类
package oop;
//一个项目应该只存在一个main方法,测试类
public class Application {
public static void main(String[] args) {
//方法的调用只和左边,即定义的类型有关
A a = new A();
a.test();
B b = new A(); //父类的引用指向子类
b.test();
}
}
运行结果:
2.非静态方法时:(重写)
//父类
package oop;
public class B {
public void test(){
System.out.println("B-test()");
}
}
//子类
package oop;
public class A extends B {
public void test(){
System.out.println("A-test()");
}
}
//测试类
package oop;
//一个项目应该只存在一个main方法,测试类
public class Application {
public static void main(String[] args) {
A a = new A();
a.test();
B b = new A(); //子类对父类的重写
b.test();
}
}
运行结果·:
3.为什么要重写
因为父类的功能,子类不一定需要,或者不一定满足。
9.多态
1.定义:
多态即同一方法可以根据发送对象不同而采用多种不同的行为方式。
2.注意事项:
1.多态是方法的多态,属性没有多态
2.存在条件:
首先得有继承关系,否则报错ClassCastException
其次方法要重写,但是 有些方法不能够被重写:1.static 2.final常量 3.private
父类引用指向子类,Father f1 = new Son();
//父类
package oop;
public class Person1 {
public void run(){
System.out.println("run");
}
}
//子类
package oop;
public class Student2 extends Person1 {
public void run(){
System.out.println("ru");
}
public void eat(){
System.out.println("eat");
}
}
//测试类
package oop;
//一个项目应该只存在一个main方法,测试类
public class Application {
public static void main(String[] args) {
// 一个对象的实际类型总是确定的
// new Student2();
// new Person1();
//但是指向引用类型就不确定了,父类的引用指向子类
Student2 s1 = new Student2();
Person1 s2 = new Student2();
Object s3 = new Student2();
s2.run();
//Student2子类型能调用的方法都是自己的,或者从父类那里继承过来的
s1.run();
//对象能执行哪个方法,主要看的是左边的类型,和右边关系不大
//Person1父类型可以指向子类,但是不用调用子类型的方法
((Student2) s2).eat();//此处是强制转换为子类,如果直接写s2.eat();这样写会报错,因为父类没有eat()方法
}
}
输出结果:
10.instanceof和类型转换
1.instanceof
定义:判断一个对象是什么类型,是否有继承关系。
//前提如下:
//建立了一个父类person2
//两个子类student3和teacher
public class Application {
public static void main(String[] args) {
Object object = new Student3();
Person2 person = new Student3();
Student3 student = new Student3();
System.out.println(object instanceof Student3);//True
System.out.println(object instanceof Person2);//True
System.out.println(object instanceof Object);//True
System.out.println(object instanceof Teacher);//flase
System.out.println(object instanceof String);//flase
System.out.println("==============================");
System.out.println(person instanceof Student3);//True
System.out.println(person instanceof Person2);//True
System.out.println(person instanceof Object);//True
System.out.println(person instanceof Teacher);//flase
//System.out.println(person instanceof String);//编译失败
System.out.println("==============================");
System.out.println(student instanceof Student3);//True
System.out.println(student instanceof Person2);//True
System.out.println(student instanceof Object);//True
//System.out.println(student instanceof Teacher);//编译失败
//System.out.println(student instanceof String);//编译失败
}
}
2.类型转换
低----->高 自然转换
高----->低 强制转换
//子类
public class Student3 extends Person2 {
public void go(){
System.out.println("go");
}
}
//测试类
public class Application {
public static void main(String[] args) {
//高转低
Person2 s = new Student3();
Student3 s1 = (Student3)s; //方法一
s1.go();
((Student3) s).go(); //方法二
//低转高
Student3 student = new Student3();
Person2 person = student;
//低转高可能会丢失自己本来的一些方法
}
}
11.static
1.静态变量
静态变量可以用类直接调用
public class Static {
private static int age;
private double score;
public static void main(String[] args) {
Static s = new Static();
System.out.println(s.score);
System.out.println(s.age);
System.out.println(Static.age); //静态变量可以用类直接调用
//System.out.println(Static.score); //非静态变量用类调用会报错
}
}
2.静态方法
静态方法可以直接调用,无需new
public class Static {
public static void go(){
run(); //报错,静态方法无法调用非静态方法,因为static方法先加载,此时非static的方法还没有
}
public void run(){
go();
}
public static void main(String[] args) {
go();
new Static().run();
}
3.静态代码块
static{
//代码
}
public class Demo05 {
//功能:可以赋初始值
{
System.out.println(" 匿名代码块");
}
//最先执行,而且只执行一次!
static {
System.out.println(" 静态代码块");
}
public Demo05() {
System.out.println(" 构造方法");
}
public static void main(String[] args) {
Demo05 s = new Demo05();
System.out.println("======================");
Demo05 s1 = new Demo05();
}
}
输出结果:
4.静态导入包
package oop;
import static java.lang.Math.random;
public class Demo06 {
public static void main(String[] args) {
//导入静态导入包后就可以不写System.out.println(Math.random());而写下面这个
System.out.println(random());
}
}
12.抽象类(abstract)
特点:
1.不能new出来,是种约束,只能靠子类去实现
2.抽象类里可以写普通方法,但抽象方法必须写在抽象类里
//abstract抽象类
public abstract class Action {
//是约束
//abstract抽象方法,只有方法名字,没有实现!需要别人(子类)帮我们实现
public abstract void dosomething();
}
//子类
//抽象类的所有方法都需要继承它的子类去实现,除非子类也是抽象类
public class Action1 extends Action {
@Override
public void dosomething() {
}
}
13.接口(interface代替了class)
特点:
1.接口是专业的约束,接口的本质是锲约,制定好后大家都要遵守,面向接口编程。
2.定义一些方法,让不同人去实现
3.方法public,abstract
4.常量public,static,final
5.接口不能被实例化,接口中没有构造方法
6.implements可以实现多个接口、多继承,extends实现单继承
7.必须重写接口中的方法
//接口类
//interface接口关键字,接口都需要有实现类,实现类在接口类名基础上加上Impl
public interface UserService {
//常量都是public,static,final
int age = 99;
//接口中所有定义的方法其实都是public,abstract
void add();
void delete();
void update();
void query();
}
//接口类
public interface TimeService {
void time();
}
//实现类
//多继承~利用接口实现多继承implements
public class UserServiceImpl implements UserService,TimeService{
@Override
public void add() {
}
@Override
public void delete() {
}
@Override
public void update() {
}
@Override
public void query() {
}
@Override
public void time() {
}
}
14.内部类(了解即可)
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);
}
}
}
//测试类
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.in(); //这是内部类的方法
inner.getID(); //10
}
}
//匿名类
public class Application {
public static void main(String[] args) {
//没有名字的初始化类,不用将实例化保存到变量中
new Apple().eat();
}
}
class Apple{
public void eat(){
System.out.println("吃苹果");
}
}
//局部内部类
public class Outer {
public void method(){
class inner{
public void in(){
}
}
}
}