java初学——面向对象

java初学——面向对象


补充关于方法的相关内容

方法的使用
程序代码越简单明了越好,为了避免重复的代码多次敲写,可以将重复的代码抽成一个方法,提高代码复用率。
方法递归
在方法里面调用自己叫做递归;

 public static void main(String[] args) {
    
    
       System.out.println("求n的阶乘");
       System.out.println(a(5));
   }
   static int  a(int n){
    
    
    if(n==1) {
    
    
        return 1;             // 当n==1时,得到结果网上返回
    }else {
    
    
        return n*a(n-1);  // 调用自己
    }
   }

如图
在这里插入图片描述
可变参数的方法
求n个数的和,要求传入参数不确定,有可能是sum(x),sum(x,y),sum(x,y,z),
sum(x,y…z),因此对于可变参数我们不能写无数个这样重复代码的方法。
因此有了对付参数不确定格式
如下:

 static int sum(int... nums){
    
     //类似于创建一个数组
        int num = 0;
        for(int i = 0 ; i<nums.length ; i++){
    
    
            num += nums[i];   //依次求和的操作
        }
        return num;
    }

方法的重载
对于一些方法,表达意思一样,但是传入参数不一样,可以用方法的重载,打到不改变方法名,是一样的操作。求两个数的和,但是没有告诉类型,我们可以以整型和浮点型为例

 public static void main(String[] args) {
    
    
       System.out.println(sum(1,5));  // 输出为6,调用第一个方法
       System.out.println(sum(1.2,5)); // 输出为6.2,调用第二个方法
   }
  static int sum(int x,int y){
    
    
       return x+y;
  }
  static double sum(double x,double y){
    
    
       return  x+y;
  }

补充关于数组的相关内容

模板如下

// 创建固定元素数组
// 		数据类型 [] 数组名称 = {数组内容1,数组内容2,.......数组内容n};
String [] name = {"张三","李四"};
System.out.println(name[0])  // 输出为张三,数组从0开始到n-1,结束,n为数组元素个数


// 创建数组,但是大小不固定
// 数组类型 [] 数组名称 = new 数据类型 [数据长度(可以为固定正数,也可以是n]
// n要在前面声明int型数的大小
String [] name= new String [5];
// 存入数据
  Scanner input = new Scanner(System.in);
      for (int index = 0 ; index < name.length ; index++){
          String str = input.next();
          name[index] = str ;
      }
          // 打印数据也叫做遍历,数组名.length也叫做该数组的大小n;
        for (int index = 0 ; index < name.length ; index++){
            System.out.println(name[index]);
        }

// 多维数组的创建,以二维数组为例
//  数组类型 [][] 数组名称 = new 数据类型 [必写n或者是固定数][(可写可不写)]
// 1.如果数组第二个不写,则还要在每个数组元素开辟几个空间形成二维数组
//   如下:
      String [][] name = new String[8(m)][];
      name[0] = new String[4(n)];  // 形成8*4/(m*n,m,n可以再前面写)个存储Sting类型的空间
多维数组类似,一层一层创建,或者直接创建固定值的
      


注:数组无论怎么样创建数组的大小一定是固定的,如果要进行扩容,重新创建更大的变量,再依次赋值进去,最后根据gc自动检测无用的,会回收之前的从而实现扩容。

数组的排序方法

冒泡排序,
思想为相邻两个元素进行比较和交换,使最大或最小的元素在其开头或者最后,随后较大的元素开始移到最大的后面,最后依次排好,就像生活中排队一样,高点的站后面,一个一个依次排队,分别和后面人比较,看比他高还是矮,矮的不动,高的往后一个,然后接着比较。

  /**
     * 这只是一种,从前往后升序,其次还有多种从后往前降序等
     *  把这个排序抽成一个方法如下
     */
static void BubbleSort(int a[]){   
    for (int i = 0 ;i<a.length ; i++){  // 外层循环控制的每次比较个数
        for(int j = 1 ; j <  a.length-i; j++){  // 内层控制每次从第一个开始比较,比较次数
            if(a[j-1]>a[j]){    // 如果前一个比后一个大,则交换
                int temp = 0;
                temp = a[j-1];
                a[j-1] = a[j];
                a[j] = temp;
            }
        }

    }
}

查找方法

直接查找

static  void Seek(int num,int a[]){
        for (int i = 0 ;i < a.length ; i++){
            if(num == a[i]){
                System.out.println("找到了,在第"+i+1+"位置上");  
                break;
            }
        }
            System.out.println("没有找到元素");
}

折半查找,面对数据很多的情况下,且数据在内部排序完成时进行

// 这个折半使用前提数据排序好的
static  void  halfSeek(int a[],int num){
        int min = 0;                 // 让初始等于数组前后坐标
        int max = a.length-1;  
        int mid = (max +min)/2; // 找到中间值
        while (true) {
            if(mid==min && mid!=num){
                System.out.println("没有找到该数");
                break;
            }
            if (num < a[mid]) {
                max = mid - 1;
            } else {
                min = mid + 1;
            }
            mid = (max + min) / 2;
            if (num == a[mid]) {
                System.out.println("找到该数了,该数的位置为第"+(mid+1)+"个元素");
                break;
            }

        }
}

面向对象基础

一切都可以皆对象,对于一个问题时都可以封装为一个类,使其保证较高的代码阅读能力和使用能力,比单纯的方法更加具有实用效应

对象

1.引入

在生活中,各种东西生物都有自己的属性和特点,比如人有自己的姓名,身份证号,家庭地址,电话号码,通过这些家庭住址,姓名就可以找到这个人,再比如说,人与动物之间有相同的特点,都要生存,休息等,这些共有属性我们也可以在程序表达,也有不同点,鸟会飞,人会使用工具,这些衍生出来的不同点,我们又可以表达属于不同的特点这些我们可以写作类。
在类中,我们也可以表达出相同的意思,一个类包括成员变量和成员方法。在成员变量和方法我们要宣称修饰符,就像生活中有的属性年龄,体重不愿意公开说,可以设置私有(private),有的得奖的方法战绩可以宣传出去就可以设置共有(public),创造实例即为对象,对象实例化用new关键字来完成,就可以使用它了。

面向对象分为三种

OOA:面向对象分析
OOD:面向对象设计
OOP:面向对象程序
同时具有三大特征:封装性,继承性,多态性。

示范代码如下(示例):

public class Person {
    
    
    // 私有一个属性年龄
    private int age;
    // 默认一个属性名字,默认为default
     String name;
    // 成员方法
    
    // 没有生成构造函数系统会默认生成一个                                  
 public Person() {
    
                    
 }                                
                                  
 public Person(String name) {
    
         // 构造函数的重载
     this.name = name;            
 }                                
 public int getAge() {
    
       // 显示年龄       
     return age;              
 }                            
                              
 public void setAge(int age) {
    
      // 获取年龄
     this.age = age;          
 }                            
	public void show(){
    
    
    System.out.println("我的名字是"+name+",我今年"+age+"岁了!");
	}
}
                                                 
 public static void main(String[] args) {
    
            
      // 生成对象 对象类型 对象名 = new 对象类型();
      Person p = new Person("张三"); 
      p.setAge(18); // 设置年龄
      p.show(); // 输出为      我的名字是张三,我今年18岁了!                     
 }                                               

注:生成对象时,在使用相应方法时,实例对象名.相应的方法操作,如上面的,p.show();
this关键字
this关键字,指的是自己实例对象的属性或者方法

 public Person() {
    
                       
     this("zhang san",18) ;    // 调用自身两参数进行初始化      
     System.out.println(name +age);  
 }                                   

注:this关键字初始化调用自身构造方法时,必须写在构造方法的第一排
不能写成下面这种形式

 public Person() {
    
         
   System.out.println(name +age);  // 报错,初始化应该加载构造函数,
   //不能使用其他的              
     this("zhang san",18) ;          
   
 }                                   

在IDEA中,按住Alt + Insert 会弹出针对对象的快捷生成方式,常用的几种功能,有的也是方法就是函数,所以写的时候把函数看成方法就行了
在这里插入图片描述
当然不用快捷键,在这里找到
在这里插入图片描述

2.基础介绍

各种方法

1.构造方法,在对象生成实例时,会做准备工作,类似于初始化这样的操作,如上面的第一个功能Constructor,可以选择无参的构造函数,也可以初始化有参数的构造方法
代码如下(示例):

public class Person {
    
                               
    public Person() {
    
                               
        System.out.println("我是构造函数");           
 	}    
 }  
 // 在主函数中
 public class Main1 {
    
    
    public static void main(String[] args) {
    
    

        // 生成对象 对象类型 对象名 = new 对象类型();
        Person p = new Person();  // 输出为:我是构造函数
   		 }      
    }                                  

2,get,和set
快捷键可以自动为你生成相关的成员设置和显示成员变量,这样做的好处在于封装在内部,private修饰的,只能通过内部方法来访问或者改变,这样更加安全可靠。

 public int get成员变量() {
     return 成员变量;              
 }                            
                              
 public void 成员变量(数据类型 成员变量) {  // 获取年龄
     this.成员变量 = 成员变量;          
 } 

3.equals()
重写equals函数,目的为了比较成员涉及的变量是否相同
如果不重写无法进行比较,只能比较单个属性,却不能得到变量整体相等
在这里插入图片描述
这里我们只勾选年龄和分数相同,就认为两个实例对象相等
生成如下

 @Override            
  // Object 是所有对象的父类,因此可以说传入一个实例对象                                         
 public boolean equals(Object o) {
    
    	
   // 本身就和上一个对象相同,true       
     if (this == o) return true; 
      // 不是这个Person这个类型,false                      
     if (!(o instanceof Person)) return false;  
        // 将传入的对象,强转成Person类型,父类强制转换为Person的一个子类     
     Person person = (Person) o;    
         // 判定勾选的年龄和分数            
     return age == person.age && score == person.score;
     
 }                                                                                                            
 @Override                                             
 public int hashCode() {
    
                                   
     return Objects.hash(age, score);                  

实际操作如下,

   Person p1 = new Person("zhang san",18,1001,98);
        Person p2 = new Person("li si",18,1002,98);
        Person p3 = new Person("wang er ma zi",19,1002,98);
        System.out.println(p1.equals(p2));  // 输出为true
        System.out.println(p2.equals(p3));  // 输出为false

4.toString
重写toString函数,如果不重写代码如下

  Person p1 = new Person("zhang san",18,1001,98);
  // 输出为com.java.class.Person@651
  // toSing是Object的一个方法,返回该文件地址+@+哈希码16位无符号字符串
  // 返回字符串表现形式,如果不重写不更加具体看到我们想看到的
    System.out.println(p1.toString());

重写后

 @Override                              
 public String toString() {
    
                 
     return "Person{" +                 
             "name='" + name + '\'' +   
             ", age=" + age +           
             ", number=" + number +     
             ", score=" + score +       
             '}';                       
 }  
 // 在主函数内输入
 //输出为Person{name='zhang san', age=18, number=1001, score=98}
  System.out.println(p1.toString());                                    
匿名对象

匿名,没有名字,只能使用一次,下次再也找不到上一个的操作了
原来对象每次使用都 对象名 名字 = new 对象名();
现在我们直接可以使用右边不取名字,调用一次的操作。
比如上面的输出默认的姓名名字年龄分数,可以直接使用
new Person().toSing;,其他调用方法一样,用生成对象的右边代替,使用一次的操作

继承与接口

继承
如果编写了一个类,但是想要完成两种属性两种操作又有区别,但是有相同点,依次有了继承,继承是继承父类的特征和行为,所以说子类有父类相同的操作,同时子类可以具有自己的行为,通过关键字extends继承于父类
语法模式
class 父类名{
}
class 子类名 extends 父类名{
}

代码如下

public class Person {
    
                              
    private String name;                       
    private int age;                           
                                               
    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;                        
    }                                          
}                                              
class Student extends Person{
    
         //继承Person             
    private int number;                        
                                               
    public int getNumber() {
    
                       
        return number;                         
    }                                          
                                               
    public void setNumber(int number) {
    
            
        this.number = number;                  
    }                                          
}
// 在主函数中,
        Person p1 = new Person();
       	Student p2 = new Student();
       	p2.setAge(18);  			// 可以用父类的方法
        p1.setNumber(123234);  	// 报错,父类无法使用子类的
                                            

继承可以多重继承,但是在java中无法多继承,即一个子类不能有多个父类,一个子类也可以被下一个所继承。
关键字super
super可以访问父类构造方法,调用父类的构造方法,就像初始化一样写在第一行,子类的构造方法,每生成一个实例就创建了一个父类,通过super可以调用父类的方法,代码如下

                                                            
  public Student(String name, int age, int number) {
    
         
  // 每次传入三个属性进来,都会生成父类构造    
      super(name, age);     
      // 默认年龄18,姓名张三                                
      super.setAge(18);                                     
      super.setName("zhang san");  
      最后,构造方法初始化为张三 18 加自己输入的number                         
      this.number = number;                                 
  }                                                         

注:在使用super关键字时,父类构造必须放在第一排,但是和this构造函数放第一排产生矛盾,其实使用super系统调用this了,不用再写this来产生错误了。
方法的重写
对于父类有自己方法,子类也想实现相同类似的操作,可以将方法进行重写,可以调用子类的该方法与父类又既有差异性。

public class Person {
    
                                  
   void say(){
    
                                         
       System.out.println("I am Person!");         
    }                                              
}                                                  
class Student extends Person{
    
         //继承Person       
                                                   
    @Override                                      
    void say() {
    
                                       
        System.out.println("I am Student!");      
         // 这样重写调用子类的方法就显示不同
    }                                              
}                                                  
                                                   

方法的重写(Override)与重载(Overload)的区别

  • 1,发生的位置不同
    • 重载是在一个类中
    • 重写是在父类与子类中
  • 2,参数的限制不同
    • 重载的参数可以不相同
    • 重写的参数必须相同
  • 3 ,返回值类型不同
    • 重载与返回值无关
    • 重写必须一致
  • 4访问权限
    • 重载与访问权限没有关
    • 重写子类的权限必须大于等于父类的权限
  • 5,异常处理
    • 重载与异常处理无关
    • 重写异常范围可以更小但是不能抛出新的区别

接口
语法格式
interface 接口名称{
全局常量;(例如;int a =1;默认为static final int a=1;全局常量
抽象方法(注,只能有抽象方法,不能有构造方法,只有名字没有实际意义)
}
抽象方法,只有方法前面的,没有{},例如void print();
实现类
class 子类 implements 父接口1 ,父接口2,父接口3,…{

}
如果又含有继承又有接口时格式如下
class 子类 extends implements 父接口1 ,父接口2,父接口3,…{

}
且接口可以继承,不同于类的继承有多继承格式如下
interface C extends A , B{

}
例如:

   interface  Person1{
    
                     
                int a = 8;             
               void print();           
      }                                
                                       
public class Person implements Person1{
    
    
                                       
    @Override                          
    public void print() {
    
                  
        System.out.println("接口的实现");   
    }                                  
}                                      
抽象类

抽象类·用 abstract class 声明
格式为
abstract class 抽象类名{
// 可以有抽象方法,也可以有构造方法
// 但是抽象方法必须有abstract修饰
public abstract void 方法名();
}

public abstract class Person2 {
    
    
    public Person2() {
    
    
        System.out.println("构造方法");
    }

    abstract void print();
}
public class Person extends Person2{
    
                  
                                                  
    @Override                                     
    public void print() {
    
                             
        System.out.println("抽象类方法的实现");           
    }                                             
}                                                 
                                                  

注意,1,抽象类无法实现,所以不能用new生成实例化
2,一个抽象类必须被子类继承,子类不是抽象类要写出所有抽象方法的实现,没有实现完也是抽象类。
3,抽象类不能被final所修饰的,因为final修饰的不能有子类,而抽象类有子类才有意义
4,抽象类可以有构造方法,先调用父类的再调用子类的构造方法,和普通类继承一样,但是我们没法手动创建抽象对象,但是在jvm(虚拟机)创建
5,抽象类必须用public或者protected修饰,用private修饰的抽象类无意义
但是接口比抽象类更加抽象,因此接口的使用更加常见,而抽象类使用较少

内部类和包装类
内部类

在一个类的里面再定义一个类,及class A{ class B{}},这种形式,相对于B来说A为外部内,对于A来说B就是内部类

class Outer {
    
                               
    private int x = 1;                  
    public int getX() {
    
                     
        return x;                       
    }                                   
    public void setX(int x) {
    
               
        this.x = x;                     
    }                                   
    class Inner{
    
                            
        public void say(){
    
                  
            System.out.println("x="+x); 
        }                               
    }                                   
}                                       

特点:内部类可以访问外部类的所有属性包括private或者static修饰的和成员方法
注意:当内部类有与外部相同的成员变量或者方法时,外部类会发生隐藏现象,及直接访问会访问到内部的,可以通过下面格式访问
外部类.this.成员变量(成员方法)
对于外部想要访问内部类结合上一张图片做下面操作

Outer outer = new Outer();
Outer.Inner inter = outer.new Inter();

根据内部类的位置分为四种:成员内部类,局部内部类,匿名内部类,静态内部类
上面也是成员内部类,外部如果不创建,无法使用内部类。
局部内部类,意思上来说就是局部的概念,有的对象我们可能只使用几次,后面就再也不会使用了,因此写到{ }内,就可以使用一次就不会再使用了。

public static void main(String[] args) {
    
    
int a = 5;
        class Name{
    
    
           // 写自己要做的成员方法或者是成员属性 
        }
        Name name = new name();
        name.xxxx;  // 程序中只使用一两次完成的操作,之后不再使用
        System.out.println(a);   // 当内部使用外部的变量,
        //外部就变为final修饰的,如果外部再将a变值则会报错
    }

局部内部类调用外部的变量,外部默认变成final不可以改变的。解释一下
(当外面一a=5,在系统会备份一次(单独编译的字节码文件),如果外面改变了,里面备份和外部不一样,会发生错误,因此java避免这种错误,所以只能访问final型。)
匿名内部类,只使用一次的类,属于局部内的一种,和局部内部类,只是使用不同

public interface Person {
    
       
   void say();              
}    
 public static void main(String[] args) {
    
    
    Person p = new Person() {
    
      // 只使用一次的匿名内部类
        @Override
        public void say() {
    
    

        } // 接口的实现
    };
    }                                      

匿名内部类,必须有一个父类或者一个接口的实现类
规则:匿名内部类不能存在静态成员或者静态方法,如果是一个接口的实现,要实现所有未实现的方法,匿名内部类属于局部内部类,只能访问final的局部变量
静态内部类和其他内部类一样,只不过在前面类用static进行修饰

class Outer {
    
                               
    private int x = 1;                  
    public int getX() {
    
                     
        return x;                       
    }                                   
    public void setX(int x) {
    
               
        this.x = x;                     
    }                                   
  static  class Inner{
    
                            
        public void say(){
    
                  
            System.out.println("x="+x); // 不可以使用外部非静态类
            //会出现错误,只有将上面改为static private int x,才可以访问
        }                               
    }                                   
} 
// 其次它和访问内部类有区别,可以生成内部类
public static void main(String[] args) {
    
    
Outer.Inner inner = new Outer.Inner(); // 直接生成内部类的对象
}
       

包装类

在系统以及做好的类,为了使我们更加便利,java提供了8种数据类型的包装类

基本数据类型 包装类
int Integer
char Character
float Float
double Double
boolean Boolean
byte Byte
short Short
long Long

除了int,char其他都是首字母大写
但是八种包装类分成两类
Character,Boolean都是Object的直接子类
Integer,Float,Double,Byte,Short,Long都是Number的子类
用到操作,常用的是将字符串转换为8种数据类型

// 以String转换为int为例
  Scanner input = new Scanner(System.in);
        System.out.println("请输入数据");
        String str = input.nextLine();// 输入2235
        int x = Integer.parseInt(str);
        System.out.println("输入的数据为"+x); // 输出为:输入的数据为2235

其他转换方法只需要把前面的改为相应的包装类即可。


总结

总结面向对象将一些具有联系的形成一个整体,更贴近于事物运行模式,面向对象让我们进一步了解程序的运行模式,让我们从工人到设计师的转变。
难点在于多个类对象的加上数组的设计与实现。复杂交错。以及细节的一些方面处理。

猜你喜欢

转载自blog.csdn.net/m0_52063248/article/details/113721747
今日推荐