JavaSE-07 Opp面向对象

JavaSE-07 Opp 面向对象

1.方法的调用补充:package com.fenfen.oop.Demo1

1.1非静态方法下方法调用(两个不同的类)

       ①在Student的类中建立study的方法
		package com.fenfen.oop.Demo1;
		//学生类的方法
        public class Student {
            //方法
            public void study(){
                System.out.println("学生在学习");
            }
        }

		②在Demo2类中调用Student类中的student方法
		//在别的类中调用
        package com.fenfen.oop.Demo1;

        public class Demo2 {
            public static void main(String[] args) {
                //在方法非静态下:实例化这个类
                //对象类型 对象名 = 对象值
                Student student = new Student();
                student.say();
                }
            }

1.2非静态方法下的方法调用(同个类中)

        public class Demo2 {
           
          //static和类(class:Demo2)一起加载
            public static void a(){
                b();//会报错原因:可以理解为:存在的去调用不存在的了
            }
            //没有static:这个得等到类实例化(new 后)才存在
            public void b(){
                a();
            }
        }

1.3 值传递:

        //值传递
        public class Demo4 {
            public static void main(String[] args) {
                int a = 1;
                change(a);
                System.out.println(a);//输出仍然是a = 1
            }

            //无返回值
            public static void change(int a){
                //原因:a只是一个形式参数,a=10后没有返回值给到a,于是回到了主方法,主方法中有int a = 1,因此输出就是1了
                a = 10;
            }


            /*
            更加高端的解释:
                ①change方法调用完毕就出栈了,main方法还在栈中
                ②对于基本数据类型来说,给形参传递的是实参值的副本
                    而对于引用数据类型来说,传递则是地址的副本,但由于地址的副本和原来的相似,因此传递过去后的形参也指向同一个内存空间
             */

1.4 引用传递:

  1. 原来代码
    public class Demo5 {
        public static void main(String[] args) {
            Person person = new Person();
            System.out.println(person.name);//null

            change(person);
            System.out.println(person.name);//fenfen
        }

        //写个方法
        public static void change(Person person){
            person.name = "fenfen";//原因:引用传递:指针修改,传递的是person的地址,地址不变,地址的内容发生了改变,底层因为指针修改,因为引用指向原对象在内存中的区域,所以可以修改原对象的值

        }
    }
    //定义了一个Person类,有一个属性:name
    class Person{
        String name;
    }

  1. 优化代码
  • 原因是因为前面的那个代码按照视频来着的,后面自己写了下,发现用了两个类不太好理解,因此有下面的仅用一个类可能比较好理解值传递的这个内容
public class Test {
    String name;

    public static void main(String[] args) {
        Test test = new Test();
        System.out.println(test.name);

        change(test);
        System.out.println(test.name);
    }



    public static void change(Test test) {
        test.name = "fenfen";
    }
		/*输出结果如下:
		null
		fenfen
		*/

2. 对象的创建与分析:com.fenfen.oop.Demo2

2.1 类和方法的创建:Student,Application

        //学生类
        public class Student {
            //①属性:字段
            String name;//未赋任何值,默认初始化为null
            int age;//为赋任何值,初始化为0

            //②方法
            public void study(){
                System.out.println(this.name+"学生在学习");//this表示当前这个类
            }
        }
        public class Application {

            public static void main(String[] args) {
                //实例化:student对象就是一个Student类的具体实例
                Student student = new Student();
                Student xiaoming = new Student();
                Student xiaohong = new Student();

                //给对象赋值:        
                xiaoming.name = "小明";
                xiaoming.age = 3;
				
				//打印后的xiaoming的方法,发现赋值的名字在里面了
				 xiaoming.study();	

                //打印赋值后的对象属性:未赋值出来是null和0
                Person person = new Person();
                System.out.println(person.name);
                }
            }   

2.2 构造器详解

2.2.1 无参构造器
		public class Person {            
        	String name;
			//1、一个类即使什么都不写,也会存在构造方法(和类名相同,且无返回值),即构造器:无参构造器
    		//构造器的作用:实例化初始值:使用new对象,本质是在调用构造器
    		public Person(){
            	this.name = "fenfen";
    					}
        public class Application {

            public static void main(String[] args) {

                Person person = new Person();
                System.out.println(person.name);//fenfen
            }
2.2.2 有参构造器
		public class Person {            
        	String name;
    		//2、有参构造器:一旦定义了有参构造,无参就必须显示定义(就是有了有参,无参不能删,空着就好)
           
            public Person(){
       			}
            
            public Person(String name){
                this.name = name;
            }
        public class Application {

            public static void main(String[] args) {

		//实例化了一个对象:走的无参构造器
        Person person = new Person();
        System.out.println(person.name);

        //走有参构造器
        Person person1 = new Person("fenfen");
        System.out.println(person1.name);
            }
        }	
		
		//注:快捷键alt+insert然后点击constructor,可以选择无参或有参快速生成构造器
2.2.3 整段代码理解
public class Studenta {
    String name;
    int age;
    
    public void study(){
        System.out.println(this.name+"学习");
    }
}

class Application{
    public static void main(String[] args) {
        Studenta xiaoming = new Studenta();
        xiaoming.name = "小明";
       /xiaoming.study();


        //走无参构造器
        Person person = new Person();
        System.out.println(person.name);

        //走有参构造器
        Person persona = new Person("yeuyue","女");
    }
}
class Person{
    String name;
    String sex;

    public Person() {
        this.name = "手写显性构造器实例化初始值";
    }

    public Person(String name, String sex) {
        this.name = name;
        this.sex = sex;
    }
}

2.3 创建对象内存分析:com.fenfen.oop.Demo3

栈的概念是弹压,就像子弹壳装弹,一粒一粒压进去,但是打出来的时候是从上面打出来的,最先压进去的最后弹出来,如果进去顺序是123,打出来顺序是321,这就是后进先出
队列的概念就是我们平时排队,按次序来,你排在第1个,那你就第一个轮到,就是先进先出,先到先来
资料补充1:https://blog.csdn.net/qwe0754444/article/details/54926707?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-3-54926707-blog-113713085.pc_relevant_multi_platform_featuressortv2dupreplace&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-3-54926707-blog-113713085.pc_relevant_multi_platform_featuressortv2dupreplace&utm_relevant_index=6
资料补充2 :https://blog.csdn.net/weixin_44688301/article/details/115632482?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-6-115632482-blog-54926707.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EOPENSEARCH%7ERate-6-115632482-blog-54926707.pc_relevant_default&utm_relevant_index=6

2.3.1 对应代码
        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.name);
                System.out.println(dog.age);
                }
            }
2.3.2 对应内存顺序图:

在这里插入图片描述

3. 三大特性

3.1 封装:com.fenfen.oop.Demo4

3.1.1 相关概念:
原因:
a.程序设计应”高内聚,低耦合“,即类的内部数据操作细节不允许外界干涉,以及仅暴露少量方法给外部使用
b.封装:应禁止直接访问一个对象中数据的实际显示,通过操作接口去访问,以便信息隐藏
3.1.2 封装
        //封装:属性私有 get/set
        public class Student2 {
            //名字、姓名、学号:一般封装对于属性来说比较多,对于方法少一些
            //学习、睡觉
            private String name;
            private int id;
            private char sex;
            private int age;

            //提供一些可以操作的这个属性的方法:因为上面private了
            //提供一些public的get、set的方法

            //①get获得这个数据
            public String getName() {
                return this.name;
            }

            //②set  给这个数据设置值
            public void setName(String name){
                this.name = name;

            }
            //注:快捷键alt+insert然后点击setter and getter,可以快速生成
            
            //③甚至可以在set里面写if判断来进行安全性检查
            public void setAge(int age) {
                if (age>120 || age<0) {
                    this.age = 3;
                }else{
                    this.age = age;
                }
            }
        }
        public class Application {

            public static void main(String[] args) {       

			Student2 s1 = new Student2();
                
            //s1.name = "fenfen";私有的不可调用
            String name = s1.getName();//get
            s1.setName("fenfen");
            System.out.println(s1.getName());//s1.getName().sout
                
            s1.setAge(999);
            System.out.println(s1.getAge());
                }
            }
3.1.3 封装的意义:
        封装的意义:
        1、提高程序的安全性,保护数据
        2、隐藏代码的实现细节
        3、统一接口
        4、提高系统的可维护性
        5、封装和重载一般一起用的比较多

3.2 继承:com.fenfen.oop.Demo5

3.2.1 子类继承父类的方法与属性
        public class Person {
            public int money = 10_0000_0000;
            public void say(){
            System.out.println("说了一句话");
        	}
        }
        public class Student extends Person{
            public static void main(String[] args) {
                Student student = new Student();
                student.say();
                System.out.println(student.money);
            }//子类继承父类,就会拥有父类的方法
3.2.2 子类继承父类私有的属性
        public class Person {
            private int money2 = 99999999;	

            //get和set方法针对private搞个封装
            public int getMoney2() {
                return money2;
        	}
            public void setMoney2(int money2) {
                this.money2 = money2;
            }
        }
        public class Student extends Person{
            
            public static void main(String[] args) {	
                
                 Student student = new Student();
                 //针对private的封装方法的调用
                student.setMoney2(99);
                System.out.println(student.getMoney2());
            }
        }
		//注:   //ctrl+h可以弹出继承树
3.2.3 super详解
  1. super在属性上的运用
  • 父类
        public class Person {
            //protected
            protected String name = "fenfen父类";
        }
  • 子类
        public class Student extends Person{
            private String name = "fenfen子类";
            
            public void test(String name){
                System.out.println(name);//main传递过来的参数
                System.out.println(this.name);
                System.out.println(super.name);//super去调用父类的
            }
        }
  • Application类
        public class Application {
             public static void main(String[] args) {
                com.fenfen.oop.Demo5.Student student1 = new com.fenfen.oop.Demo5.Student();
                student1.test("fenfenmain类");
                     }
                }
  1. super在方法上的运用
  • 父类
        public class Person {
            public void print(){//如果是私有的方法,子类就不能直接访问了
            System.out.println("Person");
        	}
        }
  • 子类
        public class Student extends Person{
            
            public void print(){
            System.out.println("Student");
        	}
            
            public void test1(){
                print();//当前方法
                this.print();//当前方法
                super.print();//父类的方法
    }
            
            
        }
  • Application类
         public class Application {

            public static void main(String[] args) {
                com.fenfen.oop.Demo5.Student student1 = new com.fenfen.oop.Demo5.Student();
                student1.test1();
            }
         }
  1. super在无参构造器上的运用
  • 父类
        public class Person {
            public Person(){
            System.out.println("Person无参执行了");
        }
            
            protected String name = "fenfen父类";
        }
  • 子类
        public class Student extends Person{
            public Student() {
                //隐藏代码:调用了父类的无参构造
                //即有一行:super();且调用父类的构造器必须在子类的第一行
    		System.out.println("子类的无参执行了");
    		}
            
            private String name = "fenfen子类";
   
        }
  • Application类:
        public class Application {
             public static void main(String[] args) {
                com.fenfen.oop.Demo5.Student student1 = new com.fenfen.oop.Demo5.Student();
                     }
                }
		/*
		Person无参执行了
		子类的无参执行了
		*/
  1. super在有参构造器上的运用
  • 父类
        public class Person {

            //整一个有参构造器
            public Person(String name){
                System.out.println("Person无参执行了");
                }
            }
  • 子类
        public class Student extends Person{

            public Student() {
                super(name:"name");//记得写参数,才会去调用有参的
                System.out.println("子类的无参执行了");
            }

                private String name = "fenfen子类";

                }
  • Application类:
        public class Application {
             public static void main(String[] args) {
                com.fenfen.oop.Demo5.Student student1 = new com.fenfen.oop.Demo5.Student();
                     }
                }
3.2.4 方法的重写:com.fenfen.oop.Demo5
  1. 提前介绍多态:有static
  • 父类
        public class B {
            public static void test(){

                System.out.println("B=>test");
            }
        }
  • 子类
        public class A extends B {
            public static void test(){

                System.out.println("A=>test");
            }
        }
  • Application类
        public class C {
            public static void main(String[] args) {
                //方法的调用只和左边的类型有关,定义的数据类型有关
                A a = new A();
                a.test();//走的是A类的方法

                //A继承B,父类的引用指向子类
                B b = new A();
                b.test();//走的B类的方法
            }

        }
  1. 方法重写:非静态
  • 父类
        public class B {
            public void test(){

                System.out.println("B=>test");
                }

            }
  • 子类
        public class A extends B{
            //重写1
            @Override//把static去掉,这个就是注解:有功能的注释
            public void test() {
                System.out.println("A=>test");
                }
            }
  • Application
        public class C {
            public static void main(String[] args) {

                A a = new A();
                a.test();//A=>test

                B b = new A();
                b.test();//A=>test
            }
        }

总结看看:

        /*第二次用重写的没有static的结果截然不同:
        有static静态时:b调用的是B类的方法,因为b是用B类去定义的
        没有static静态时:b调用的是对象的方法,b是用A类new的
        
        重写:需要有继承关系,而且是子类重写父类
        1、方法名必须相同
        2、参数列表必须相同
        3、修饰符:范围可以扩大:
            private--->default---->protected---->public
        4、重写可能会抛出异常:范围可以被缩小,但不能被扩大
            ClassNotFoundException

    	注意:子类的方法和父类必要一致:方法体不同

    	为啥要重写:override
        1、父类的功能子类不一定需要,或者不一定满足

3.3 多态:com.fenfen.oop.Demo6

3.3.1 多态的创建
        public class Main {
            public static void main(String[] args) {
                //一个对象的实际类型是确定的
                //new Student();
                //new Person();

                //可以指向的引用类型就不确定了
                Student s1 = new Student();//Student能调用的方法都是自己或者是继承来的:Student类继承了Person类
                //①父类的引用指向子类的类型
                Person s2 = new Student();//父类的可以指向子类,但是不能调用子类特定的方法
                //②指向Object
                Object s3 = new Student();
                    }
            }
3.3.2 多态方法的调用
  • 父类
        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 void go(){
                System.out.println("go");
            }
        }
  • Application
        public class Main { 	
            public static void main(String[] args) {

            Student s1 = new Student();

            Person s2 = new Student();

            s2.run();//子类重写了父类的方法,因此父类的方法调用的时候变成子类了
            s1.run();
            s1.eat();
            ((Student)s2).eat();//强制转换(高类型转成) ,Person里面没有eat方法,所以强制转换成Student去调用
                }
            }

总结一下 :

        /*
        多态注意事项:
        1、多态是方法的多态,属性没有多态
        2、父类和子类,有联系   如不符合:会出现异常ClassCastException!
        3、存在条件:①继承关系②方法需要重写③父类引用指向子类对象 Father f1 = new Student();
           有些方法不能重写:
           ①static静态,修饰的方法,属于类,不属于实例
           ②final常量,修饰的
           ③private方法:
        */
3.3.3 instance of和类型转换
  1. instance of
    	public static void main(String[] args) {
        //Object > String
        //Object > Person > Student
        //Object > Person > Teacher

        Object student2 = new Student();
        //instanceof判断左边对象是否是右边类的一个实例
        System.out.println(student2 instanceof Student);//看看是不是Student类型呢true
        System.out.println(student2 instanceof Person);//看看是不是Student类型呢true
        System.out.println(student2 instanceof Object);//看看是不是Student类型呢true
        System.out.println(student2 instanceof Teacher);//看看是不是Student类型呢false     
            											//因为没有new:object和Teacher
        System.out.println(student2 instanceof String);//看看是不是Student类型呢false
            
                }
		}
       /*总结一波:
        System.out.println(X instanceof Y);能不能编译通过取决于X、Y有没有父子关系
         */

  1. 类型转换
  • 父类
        public class Person {
            public void run(){
                System.out.println("run");
                }

                }
  • 子类
        public class Student extends Person{
            public void go(){
                System.out.println("go");
            }
        }
  • Application类
        public class Main3 {
            public static void main(String[] args) {

                //父类                子类
                //高                  低
                Person student = new Student();
                //student.go();报错原因:student属于Person,Person中没有go
                //student将这个对象转换未Student类型,我们就可以使用Student类型的方法了:高往低走
                
                Student student1 = (Student) student;//(Student)student;
                student1.go();
                ((Student)student).go();//前面写成一句话完成类型转换
                
                
                //低                 高
                //子类转换为父类,可能回丢失原来自己的方法
                Student student2 = new Student();
                student2.go();
                //把student变成person类型
                Person person = student2;
                //person.go();就用不了了
                
                }
            }
3.3.4 static关键字详解:com.fenfen.oop.Demo7
  1. static在属性上的使用
        public class Student {
            //静态属性
            private static int age;//静态的变量
            private double score;//非静态变量
             public static void main(String[] args) {
                student student = new Student();

                //用对象输出
                System.out.println(student.score);//student.score.sout
                //用类输出
                System.out.println(Student.age);
                //System.out.println(Student.score);没有static这个就不行
                //或者直接输出
                System.out.println(age+"kkkkk");
                     }
        		}
  1. static在方法上的使用
        public class Student {
            //静态方法
            public void run(){
			}

            public static void go(){
            }
        public static void main(String[] args) {
                Student student = new Student();
                //方法调用
                //用对象调
                student.run();
                student.go();
                //用类调
                Student.go();
                //Student.run();没有static这个就不行:具体原因,现在是静态方法,只能去调静态方法的
            	//直接调
            	go();
        		}
			}
            	
  1. 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();
            }
        }
/*
静态代码块儿,这个反而执行的时候是最先的,而且我就跑一次,后面不玩了
匿名代码块儿,一般会根据对象每次都跑,所以会被用来赋予初始值
构造方法
===============
匿名代码块儿,一般会根据对象每次都跑,所以会被用来赋予初始值
构造方法
*/
  1. static在静态导入包的使用
       package com.fenfen.oop.Demo7;

        //静态导入包的方法和常量
        import static java.lang.Math.random;
        import static java.lang.Math.PI;

        public class Test {
            public static void main(String[] args) {
                //System.out.println(Math.random());  不想怎么写可以在前面直接导包,但是记得写static
                System.out.println(random());
            }

4. 抽象类和接口:com.fenfen.oop.Demo8

4.1 抽象类

4.1.1 抽象对象和方法的建立
        public abstract class Action {

            //约束
            //abstrct ,抽象方法,只有方法名字,没有具体的方法内容实现,并且抽象方法跟抽象类
            public abstract void doSomething();
            
            /*
            1、不能在这个抽象类new(在main中都不给new,只能靠子类去实现它(重写?
            2、抽象类中可以写普通的方法
            3、抽象方法必须在抽象类中
            抽象的抽象:约束

            抽象存在的意义:
            		例如游戏中,抽象出一定的内容,每创建一个角色就去继承这个抽象类,直接重写部分方法,改掉一些不必要的东西即可

             */
4.1.2 无法在其他类中new一个抽象类的对象
        public class Main {
            public static void main(String[] args) {
               // new Action(); 不给new
            }
        }
4.1.3重写抽象的方法
        public class A extends Action{
            //继承用了abstract的类会报错,必须得重写一下才可以
            //抽象类得所有方法,继承了他的子类,都必须要实现他的方法
            @Override
            public void doSomething() {
            }
        }

4.2 接口:com.fenfen.oop.Demo9

4.2.1 创建接口以及基本方法
        //接口:用interface
        // 写简单方法,然后有一个对应实现类UserServiceimp
        public interface UserService {

            //public void run(){   此处需要加上abstract不然不给写方法
            //}

            //接口中的所有定义其实都是抽象的 public abstract的方法
            public abstract void run();
            void add(String name);
            void delete(String name);
            void update(String name);
            void query(String name);
            //接口中定义属性:就是一个常量,很少在接口中定义常量:默认public static final
            public static final int AGE = 99;
        }		


		public interface TimeService {
    	void timer();

		}
4.2.2 接口对应的实现类
        //一个类实现接口 implemnts 接口:可以继承多个接口
        //实现了接口中的类,就需要重写接口中的方法
        public class UserServiceimp implements UserService,TimeService{//可以实现多个接口,实现多继承

            //右击generate:implement methods或者ctrl+i快捷键

            @Override
            public void run() {

            }

            @Override
            public void add(String name) {

            }

            @Override
            public void delete(String name) {

            }

            @Override
            public void update(String name) {

            }

            @Override
            public void query(String name) {

            }

            @Override
            public void timer() {

            }

5 内部类:com.fenfen.oop.Demo10

5.1 类中类

5.1.1创建内中类
        public class Outer {

            private int id = 10;
            public void out(){System.out.println("这是外部类的方法");}

            //类内部类;类中类
            public  class Inner{
                public void in(){System.out.println("这是内部类的方法");}

                //获得外部类的私有属性:外部出现的id = 10
                public void getID(){
                System.out.println(id);
            }


            //可以在内部类Inner前加上static:
                // 但是会出现:静态的内部类无法访问非静态的内部属性
            }
        }
5.1.2 实例化并调用类中类
        public class Main {
            public static void main(String[] args) {
                //new
                Outer outer = new Outer();

                //通过这个外部类来实例化内部类
                Outer.Inner inner = outer.new Inner();//outer.new Inner();
                inner.in();
                inner.getID();
            }
        }

5.2 局部内部类(方法中的类)

        public class Outer3 {
            //方法中的类:叫做局部内部类
            public void method(){

                class Inner{
                    public void in(){
                    }
                }
            }
        }

5.3 匿名内部类

        public class Outer4 {

            public static void main(String[] args) {

                //一般是Apple apple = new Apple();
                //也可以是:没有名字初始类,不用将实例保存到变量中
                new Apple().eat();

                //接口重写下方法
              	new UserService()
                //实际写全是:UserService userService = new UserService()
                {

                    @Override
                    public void hello() {

                    }
                };
            }
        }

        class Apple{
            public void eat(){
                System.out.println("1");
            }
        }
        //整一个接口
        interface UserService{
            void hello();

        }	
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值