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)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-28一步到位:购买适合 SEO 的域名全攻略
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign学习入门:轻松掌握微服务通信
- 2024-12-27OpenFeign学习入门:轻松掌握微服务间的HTTP请求
- 2024-12-27JDK17新特性学习入门:简洁教程带你轻松上手
- 2024-12-27JMeter传递token学习入门教程
- 2024-12-27JMeter压测学习入门指南
- 2024-12-27JWT单点登录学习入门指南
- 2024-12-27JWT单点登录原理学习入门