java基础(2)

2021/6/27 22:22:41

本文主要是介绍java基础(2),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

面向对象:当需要实现一个功能的时候,不关心具体的步骤,而是找一个已经具有该功能的人,来帮助我做事。(偷懒) 面向过程:当需要实现一个功能的时候,每一个具体的步骤都要亲历亲为,详细处理每一个细节。 打印数组: JDK提供给我们一个Arrays类,其中有一个toString方法,直接就能把数组变成想要的格式的字符串Arrays.toString(数组名字) 面向对象对象思想更符合我们的思考习惯,能把复杂的事情简单化,并将我们从执行者变成指挥者。(封装、继承、多态)   类是相关属性和行为的集合。   类是抽象的,对象是具体的 成员变量是直接定义在类当中的,在方法外边。      成员方法不要写static关键字。   通常情况下,创建一个类不能直接使用,需要根据类创建一个对象,才能使用。(引用类型一般使用步骤也是如此)      1.导包:也就是指出需要使用的类在什么位置。  import 包名称.类名称;(对于和当前类属于同一个包的情况,可以省略导包语句不写)          (只有java.lang包下的内容不需要导包,其他的包都需要import语句)      2.创建      3.使用,分为两种情况:                    使用成员变量:对象名.成员变量名                    使用成员方法:对象名.成员方法名(参数)   对象内存图: 首先从方法区中将main方法放到栈(压栈)运行;在堆创建对象,从方法区中复制一份成员变量,放到堆中,赋给成员变量默认值;堆成员方法中存放在方法区中的地址;根据栈中的变量名地址找到堆中成员变量赋值,根据栈方法名地址先去堆中找地址,再根据堆中地址去方法区中找方法,运行完成的成员方法,成员变量会立刻出栈。 当一个对象作为参数,传递到方法当中时,实际上传递进去的是方法的地址值。 当使用一个对象作为方法的返回值时:返回值其实就是对象的地址值。   成员变量与局部变量的区别:          1.定义位置:                           局部变量定义在方法的内部。                          成员变量定义在类中,方法外部                 2.作用范围不一样:局部变量在方法当中才可以使用,出了方法就不能用;成员变量:整个类全都可以使用。          3.默认值不一样:                    局部变量没有默认值,如果想使用,必须手动进行赋值。                    成员变量如果没有赋值,会有默认值,规则和和数组一样。          4.内存的位置不一样:局部变量位于栈内存,成员变量位于堆内存          5.生命周期:局部变量:随着方法进栈而诞生,随着方法出栈而消失;  成员变量:随着对象创建而诞生,随着对象的销毁而销毁。   面向对象三大特征:封装、继承、多态          1.封装在java中的体现:方法是一种封装,关键字private是一种封装。封装就是将一些信息隐藏起来对外不可见。               间接访问private成员变量,就是定义一对儿Getter/Setter方法。必须叫setXxx或者getXxx命名规则。               对于Getter来说,不能有参数,返回值类型和成员变量对应。               对于Setter来说,不能有返回值,参数类型和成员变量对应。               对于基本类型中的boolean值,Getter方法一定要写成isXxx的形式,而SetXxx规则不变。  当方法的局部变量和类的成员变量重名的时候,根据“就近原则”,优先使用局部变量,如果需要访问本类当中的成员变量,需要使用格式:this.成员变量名   【【构造方法】】              构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法,格式:                         public 类名称(参数类型 参数名称){ 方法体 } 注意事项:1.构造方法方法名称与类名完全相同 2.不能写返回值类型,包括void 3.构造方法不能return一个具体的返回值                4.如果没编写任何一个构造方法,那么编译器将会默认赠送一个构造方法,没有参数,方法体中什么都没有。           一个标准的类通常要拥有下面四个组成部分:                  1.所有的成员变量都要使用private关键字修饰                  2.为每一个成员变量编写一对Getter/Setter方法                  3.分别编写一个无参的构造方法和全参的构造方法                                         这样的标准类也叫做 Java Bean           Code》Generate(Alt+Insert)  自动生成Getter/Setter方法和构造方法
  API使用方法:看包路径,看构造方法,看成员方法      Scanner sc=new Scanner(System.in);      //System.in 代表从键盘进行输入 获取键盘输入的一个int数字:int num=sc.nextInt(); 获取键盘输入的一个字符串:String str=sc.next();   匿名对象的方式:   int num=new Scanner(System.in).nextInt();       匿名对象还可以作为方法参数传入和方法返回值传出 用 Random 生成随机int数字(范围是int所有范围,有正负两种) Random r=new Random(); 获取一个int数字(参数代表范围,左闭右开区间),int num =r.nextInt(3)   实际上代表的含义是:[0,3)   数组的长度不可以发生改变,但是ArrayList集合的长度是可以随意变化的。 对于ArrayList 来说,有一个尖括号<E>代表泛型。 泛型,也就是装在集合当中的所有元素全都是什么类型。 泛型只能是引用类型,不能是基本类型。 从JDK1.7开始,右侧的尖括号内部可以不写内容,但是<>括号本身还是要写的。ArrayList<String> list=new ArrayList<>();   public boolean add(E e):向集合当中添加元素,参数的类型和泛型一致;对于ArrayList集合来说,add添加动作一定是成功的,所以返回值可用可不用。但是对于其他集合(今后学习),不一定成功。 public E get(int index):从集合中获取元素,参数是索引编号,返回值就是对应哪个位置的元素。 public E remove(int index):从集合当中删除元素,参数是索引编号,返回值就是被删除掉的元素。 public int size(): 获取集合的尺寸长度,返回值是集合中包含的元素个数。 从JDK 1.5+开始,支持自动装箱、自动拆箱。     char>>Character           int>>Integer   java.lang.String类代表字符串:java程序中所有的字符串字值(如"abc")都作为此类的实例实现 字符串的特点: 1.字符串的默认值用不可变  2.正是由于字符串的默认值不可改变,所以字符串是可以共享使用的。 3.字符串效果上相当于char[]字符数组,但是底层原理是byte[]字节数组。 创建字符串:(3+1)      三种构造:public String()     public String(char[] array)     public String(byte[] array)      一种直接:String str="Hello"; 对于引用类型来说,==进行的是地址值的比较;双引号写的字符串在常量池当中(JDK1.7后常量池放在堆中),new出的不在池当中。 如果需要堆字符串的内容进行比较,可以使用两个方法:          public boolean equals(Object obj):参数可以是任意对象,只有参数是一个字符串并且内容相同的才会给true,否则返回false     注意:Object可接收任何对象; equals具有对称性; 如果比较,一个常量,一个变量,推荐把常量字符串写在前面双方。 如果变量写在前面如果为null会发生NullPoinerException.      public boolean equalsIgnoreCase(String str): 忽略大小写,进行内容比较。  String 当中与获取相关的常用方法:          public int length()                   public String concat(String str)          public char charAt(int index):获取指定索引位置的单个字符。(索引从0开始)          public int indexOf(String str):查找参数字符串在本字符串当中首次出现的索引位置,如果没有返回-1。 字符串的截取:      public String substring(int index):截取从参数位置一直到字符串末尾,返回新字符串。      public String substring(int begin,int end):截取从begin开始,一直到end结束,中间的字符串。[begin,end) String当中与转换相关的常用方法:      public char[] toCharArray():将当前字符串拆分成字符数组作为返回值。      public byte[] getBytes(): 获取当前字符串底层的字节数组。      public String replace(CharSequence oldString,CharSequence newString);将所有出现的老字符串替换成新的字符串,返回替换之后的结果新字符串。   分割字符串的方法 :      public String[] split(string   regex):按照参数的规则,将字符串切分成若干部分。 注意事项: split方法的参数其实是一个“正则表达式”,如果按照英文"."进行拆分,必须写成“\\.”(两个反斜杠)   一旦用了static关键字,那么这样的内容不再属于对象自己,而是属于类的,所以凡是本类的对象,都共享同一份。 静态变量:类名称.静态变量 静态方法:类名称.静态方法() 如果没有static关键字修饰,那么必须首先创建对象,然后通过对象才能使用它。 如果有,那么不用创建对象对象就可以直接通过类名调用,也可通过对象名调用(不推荐,不好辨别是不是静态方法,在编译之后也会被javac翻译成为”类名称.静态方法名()“) 注意事项:      1.静态不能直接访问非静态。      原因:内存中现有的静态内容,后有的非静态内容。      2.静态方法中不能用this      原因:this代表当前对象,通过谁调用的方法,谁就是当前对象。      static修饰的成员变量在方法区中的静态区    静态代码块:当第一次用到本类时,静态代码块执行的唯一一次;静态内容总是优先于非静态,所以静态代码块比构造方法先执行。static{}     静态代码块的典型用途:用来一次性地对静态成员变量进行赋值。
   java.util.Arrays是一个与数组相关的工具类,里面提供了大量的静态方法,用来实现数组常见的操作。   public static String toString(数组):将参数数组变成字符串(按照默认格式:[元素1,元素2,元素3...]) public static void sort(数组):按照默认升序(从小到大)对数组的元素进行排序。 如果是数值,sort默认按照升序从小到大;如果是字符串,sort默认按照字母升序;如果是自定义的类型,那么这个自动的类需要有Comparator或者Comparable接口的支持。   java.util.Math类是数学相关的工具类,里面提供了大量的静态方法,完成与数学相关的操作。 public static double abs(double num): 获取绝对值,有多种重载。 public static double ceil(double num):向上取整 public static double floor(double num): 向下取整 public static long round(double num):四舍五入(返回值没有".") Math.PI代表近似的圆周率常量(double)   起点位置-10.8应该转换为-10,两种办法:      1.可以用Math.ceil方法,向上(正方向)取整      2.强转为int,自动舍弃所有小数位。
【【继承】】 继承中成员变量的访问特点: 在父类的继承关系当中,如果成员变量重名,则创建子类对象时,访问有两种方式: 直接通过子类对象访问成员变量 :等号左边是谁(的引用),就优先用谁,没有则向上找。 间接通过成员方法访问成员变量 :该方法属于谁,就优先用谁,没有则向上找。 继承中成员方法的访问特点:      在父子类的继承关系中,创建子类对象,访问成员方法的规则: 创建的对象是谁,就优先用谁,如果没有则向上找。      无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类。   区分ang子类方法中重名的三种变量:      局部变量: 直接写成员变量名      本类的成员变量:this.成员变量名      父类的成员变量:super.成员变量名        重写(Override):“方法的名称一样,参数列表也一样。覆盖、覆写      重载(Overload):方法的名称一样,参数列表不一样。 方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。(new的是谁用的就是谁)                 注意事项:                              1.必须保证父子类之间的方法名称相同,参数列表也相同。@Override:写在方法前,用来检测是否有效的正确覆盖重写,这个注解就算不写,只要满足要求,也是正确的方法覆盖重写。                              2. 子类方法的返回值必须 小于等于 父类方法的返回值范围;Object是所有类的父类。                              3.子类方法的权限必须  大于等于 父类方法的权权限修饰符    public>protected>(default)>private   继承关系当中,父子类构造方法的访问特点:      1.子类构造方法当中有一个默认隐含的”super()“调用,所以一定是先调用的父类构造,后执行的子类构造。      2.子类构造可以通过super关键字来调用父类重载构造。      3.super的父类构造调用,必须是子类构造方法的第一个语句,不能一个子类构造调用多次super构造。      4.只有子类的构造方法才能调用父类的构造方法。      总结: 子类必须先调用父类构造,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一行。   super关键字用来访问父类内容,super关键字的三种用法:      1.在子类的成员方法中,访问父类的成员变量。      2.在子类的成员方法中,访问父类的成员方法。      3.在子类的构造方法中,访问父类的构造方法。 而this关键字用来访问本类内容,也有三种用法:      1.在本类的成员方法中,访问本类的成员变量。      2.在本类的成员方法中,访问本类的另一个成员方法。      3.在本类的构造方法中,访问本类的另一个构造方法。          在第三种用法中要注意:      A.this(...)也必须是构造方法的第一个语句,唯一一个。      B.super和this两种构造调用,不能同时使用。   在同一个类中,Java普通方法的互相调用可以省略this+点号,而直接使用方法名+参数。因为Java编译器会帮我们加上。 Java语言是单继承,一个类的直接父类只能有唯一一个。可以多级继承;一个父类可以有多个子类。 如果父类当中的方法不确定如何进行{}方法体的实现,那么这就应该是一个抽象方法。   抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束。 抽象类:抽象方法所在的类,必须是抽象类才行。在class之前加上abstract即可。 抽象方法只在抽象类中,抽象类中可以有普通成员方法。抽象类中,不一定含有抽象方法。
    如何使用抽象类、抽象方法:      1.不能直接创建new抽象类对象。      2.必须用一个类来继承抽象父类。      3.子类必须覆盖重写抽象父类当中所有的抽象方法。(或者子类也是抽象方法)          覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。      4.创建子类对象进行使用。   将鼠标方法抽象子类红线处,Alt+回车选择implement methods,自动将抽象父类相关方法打印出来。    
接口是多个类的公共规范,是一种引用数据类型,最重要的内容是其中的抽象方法, 如何定义一个接口的格式:public interface 接口名称(){ //接口内容} 备注:换成了关键字之后,编译生成的字节码文件仍然是:.java --> .class 如果是java 7,接口中可以包含的内容:1.常量  2.抽象方法 如果是java 8 ,还可以额外包含有:3.默认方法  4.静态方法 如果是java 9,还可以额外包含有: 5.私有方法   在任何版本的Java中,接口都能定义抽象方法。 格式:   [public] [abstract] 返回值类型 方法名称(参数列表); 注意事项: 1.接口当中的抽象方法,修饰符必须是两固定的关键字:public abstract 2.这两个关键字修饰符,可以选择性地省略。 3.方法的三要素,可以随意定义。   接口的使用步骤:      1.接口不能直接使用,必须有一个“实现类”来"实现"该接口。      格式:               public class 实现类名称 implements 接口名称{  //... }      2.接口的实现类必须重写(实现)接口中所有的抽象方法。实现:去掉abstract关键字,加上方法体大括号。      3.创建实现类对象,进行使用。(实现类名字建议在接口名后加Impl来命名)   默认方法格式:                    [public] default 返回值类型 方法名称(参数列表){ 方法体 }              备注:接口当中的默认方法,可以解决接口升级的问题。   1.接口的默认方法,可以通过接口实现类对象,直接调用。 2.接口的默认方法,也可以被接口实现类进行覆盖重写。   接口当中定义静态方法格式:          public staitc 返回值类型 方法名称(参数列表){ 方法体 } 提示 :就是将abstract或者default换成static即可,带上方法体。   注意事项:不能通过接口实现类的对象来调用接口当中的静态方法。 正确用法: 通过接口名称,直接调用其中的静态方法。 格式:  接口名称.静态方法名(参数);   问题:我们需要抽取出一个共有方法,来解决两个默认方法之间重复代码的问题,但是这个共有方法不应该让实现类使用,应该是私有化的。 解决方案:  从Java 9开始,接口中允许定义私有方法:          1.普通私有方法,解决多个默认方法之间重复代码问题。                   格式:private 返回值类型 方法名称(参数列表){ 方法体 }          2.静态私有方法:解决多个静态方法之间重复代码问题(只有接口自己才能使用,不能被实现类或者别的类调用)                    格式:private static 返回值类型 方法名称 (参数列表){方法体}   常量:接口中也可以定义”成员变量“,但是必须使用 public static final 三个关键字进行修饰  格式:public static final 数据类型 常量类型=数据值; 注意事项:1.接口当中的常量可以省略 public static final 三个关键字,注意,不写也是这样。 2.接口当中的常量必须进行赋值            3.接口当中常量的名称,使用完全大写的字母,用下划线进行分隔。   在Java 9+版本中,接口的内容可以有:      1.成员变量其实就是常量;      2.接口中最重要的就是抽象方法。          格式:[public ][abstract] 返回值类型 方法名称(参数列表); 使用接口的时候,需要注意:      1.接口是没有静态代码块和构造方法的。      2.一个类的直接父类是唯一的,但是一个类可以同时实现多个接口。      格式:public class MyInterfaceImpl implements MyInterfaceA,MyInterfaceB{//覆盖重写所有抽象方法}      3.如果实现类所实现的多个接口当中,存在重复的抽象方法,那么只需要覆盖重写一次即可。      4.如果实现类没有覆盖重写所有接口当中的所有抽象方法,那么实现类就必须是一个抽象类。      5.如果实现类所实现的多个接口当中,存在重复的默认方法,那么实现类一定要对冲突的默认方法进行覆盖重写。      6.一个类如果直接父类当中的方法,和接口当中的默认方法产生了冲突,优先使用父类当中的方法。      1.类与类之间是单继承的,直接父类只有一个。 2.类与接口之间是多实现的,一个类可以实现多个接口。 3.接口与接口之间是多继承的。 注意事项:      1.多个父接口当中的抽象方法如果重复,没关系重写覆盖一次就好。      2.多个父接口当中的默认方法如果重复,那么子接口必须进行默认方法的重写覆盖。【而且带着default关键字】      
【【多态】】          extends继承或者implements实现,是多态性的前提;一个对象有多种形态,这就是对象的多态性      代码当中体现多态性,其实就是 父类引用指向子类对象。      格式:          父类名称  对象名=new 子类名称();     或者   接口名称 对象名=new 实现类名称();       访问成员变量两种方式:               1.直接通过对象名称访问成员变量;看等号左边是谁,优先用谁,没有则向上找。               2.间接通过成员方法访问成员变量,看该方法属于谁,优先用谁,没有则向上找。        在多态的代码当中,成员方法的访问规则是: 看new的是谁,就优先用谁,没有则向上找。                     口诀:  成员变量:编译看左边,运行还看左边;    成员方法:编译看左边,运行看右边。              父类引用指向子类对象,如果访问子类有而父类没有的方法:  obj.methodZi();//错误写法      多态好处:无论右边new出来的时候换成哪个子类对象,等号左边调用方法都不会改变。   1.对象的向上转型其实就是多态写法,向上转型一定是安全的,从小范围转向了大范围。 向上转型也有弊端:对象一旦向上转型为父类,那么就无法调用子类原本特有的内容。解决方案:用对象的向下转型【还原】 2.对象的向下转型,其实是一个【还原】动作      格式: 子类名称 对象名 =(子类名称)父类对象;      含义: 将父类对象,【还原】成为本来的子类对象;      Animal animal=new Cat();//本来是猫向上转型成为动物 Cat cat=(Cat)aniaml;//本来是猫已经被当成动物了,换回来成为本来的猫。 注意事项: a.必须保证对象本来创建的时候,就是猫,才能向下转型为猫。 b.如果对象创建的时候本来不是猫,现在非要向下转型为猫,就会报错。 java.lang.ClassCastExcepion;类转异常       类似于: int num=(int)10.0//可以       int num=(int)10.5//不可以,精度损失   向下转型要用instanceof进行判断,如何才能知道一个父类引用的对象,本来是什么子类? 格式:    对象  instanceof 类名称 这将会得到一个boolean值结果,也是判断前面的对象能不能当做后面类型的实例。   对象也能自动从子类型转换成父类型,类似于基本类型的自动类型转换: double d=10;   结果d为10.0
  native:用来声明本地方法,该方法的实现由非java 语言实现,比如C。一般用于java与外环境交互,或与操作系统交互。      final关键字:       当final关键字修饰一个类的时候,格式: public final class 类名称{//   ...}                        含义:当前这个类不能有任何子类。(太监)                        注意:一个类如果是fianl的,那么其中的成员方法都无法进行覆盖重写(因为没儿子)      当final关键字用来修饰一个方法的时候,这个方法就是最终的方法,也就是不能被覆盖重写,格式:修饰符 final 返回值类型 方法名称(参数列表){}                        注意:对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。      一旦使用final修饰局部变量,那么这个局部变量就不能更改。(只能一次赋值,不能改变)          //final int num=200;          //num=250;//错误           对于基本类型来说,不可变是变量当中的数据不可变;对于引用类型来说,不可变是变量当中的地址值不可改变。      对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变。      1.由于成员变量具有默认值,所以用了final之后必须手动赋值,不会给默认值了。      2.对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值。二值只能选其一。      3.必须保证类中所有重载的构造方法,都最终会对final的成员变量进行赋值。        四种权限修饰符: private 本类                                [default] 同包                                protected 同包和子类                                public 所有类   【【内部类分类】】          1.成员内部类               格式:                         修饰符 class 外部类名称{                              修饰符 class 内部类名称{                                      //..                                                  }                                        //..                          }               注意:内用外,随意访问,外用内,需要内部类对象                内部类编译后的类名称Person$Heart.class               show in explore     打开项目文件夹               Recompile "类名称.java" 重新编译类               ==========================================                  如何使用成员内部类?两种方法:                      1.间接方式:外部类的方法当中,使用内部类;然后main只是调用外部类的方法。                      2.直接方式,公式:                              【外部类名称.内部类名称 对象名=new 外部类名称().new 内部类名称();】                    内部类成员变量如果出现重名,在内部类的方法中:                                         this.num  //访问内部类的成员变量                                        Outer.this.num  //访问外部类的成员变量          2.局部内部类(包含匿名内部类)                    定义格式:                                 修饰符 class 外部类名称{                                             public 返回值类型 外部类方法名称(参数列表){                                                 class 局部内部类名称{                                                         // ...                                                       }                              }                         }                   小结以下类的权限修饰符:                          public>protected>[default]>private                   定义一个类的时候,权限修饰符:                           1.外部类:public/(default)                           2.内部类:public/protected/[default]/private                           3.局部内部类:什么都不能写   局部内部类,如果想要访问所在方法的局部变量,那么这个局部变量要求必须是【有效的fianl的】。 备注 从Java8.0+开始,只要局部变量事实不变,那么final关键字就可以省略。 原因:           1.new出来的对象在堆内存当中。          2.局部变量是跟着方法的,在栈内存当中。          3.方法运行结束会立刻出栈,内存变量就会立刻消失。          4.但是new出来的对象会在堆当中持续存在,直到垃圾回收消失。   如果接口的类名称(或者是父类的子类)只需要使用唯一的一次。这种情况下可以省略掉该类的定义,而改为使用【匿名内部类】。 匿名内部类的定义格式:          接口名称 对象名=new 接口名称(){                       //覆盖重写接口的所有抽象方法                  }; 对格式“new 接口名称(){...}”进行解析           1.new代表创建对象的动作   2.接口名称就是匿名内部类需要实现哪个接口   3.{...}这才是匿名内部类的内容 注意问题:          1.匿名内部类在创建对象的时候,只能使用唯一一次。如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了。          2.匿名对象,在调用方法的时候,只能调用唯一一次。如果希望同一个对象,调用多次方法,那么就必须给对象起个名字。          3.匿名内部类就是省略了【实现类/子类名称】,但是匿名对象就是省略了【对象名称】。   //使用了匿名内部类,而且省略了对象名称,也是匿名对象。                new MyInterface() { @Override public void method1() { System.out.println("方法三"); }   @Override public void method2() { System.out.println("方法四"); } }.method1();   类和接口都可以作为成员变量类型。任何一种数据类型都可以作为成员变量的类型。 接口可以作为方法的参数和返回值。

这篇关于java基础(2)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程