我是靠谱客的博主 忧伤外套,最近开发中收集的这篇文章主要介绍Java二运算符动态数组算法案例重载继承和多态静态抽象和接口superinstanceof和强转包和权限内部类附录:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

运算符

计算机工作的原理就是计算,否则也不会叫计算机,所以每种语言都对计算进行了很好的支持,Java中有丰富的运算符来支撑计算。Java中运算符大致分为以下几类:

类型符号
1.算术运算符+、-、*、/、%、++、–
2.关系运算符==、!=、>、<、>=、<=
3.位运算符&、或、^、~ 1、<< 2、>> 3、>>> 4 作用于整数和char类型上
4.逻辑运算符&&、或或、!
5.赋值运算符=和算术运算符的结合
6.其他运算符条件运算符?:、instanceof

优先级:

类别操作符
-()、. 点(调用)
一元!、~、++、-- 5
乘除*、/、%
加减+、-
位移<< 、>>、>>> (arr1.length+arr1.length>>1)
关系==、!=、>、<、>=、<=
&
^
6
逻辑&&、
三目?:
赋值=、乘除、加减、位移和赋值混合

动态数组

数组的元素个数是固定的,如果数组满了可不可以自动让数组扩容呢?通过程序来处理是可以达到的,但是此数组其实已经不是原来的数组了。
假如有一个班级对象clazz,这有一个方法addStudent,这个方法的参数是Student对象,当我们调用addStudent方法添加学生时,在clazz对象中有一个students数组来存放学生对象,但是当数组满了后,就要创建一个新的数组,这个数组要比原数组大,并把原数组中的学生对象转移到新数组中,并把原数组释放了,这样就成了动态数组,只要调用addStudent者愿意,它就可以一直给clazz添加学生。开发中当数组满时,创建的新数组大小不会是比原数组多一个元素,这样会在后续加入学生时,每次都创建新数组,转移数组元素,释放原数组,效率太低,往往创建的新数组大小是原数组的1.5倍大小。

        int oldCapacity = elementData.length;
        // (oldCapacity >> 1)相当于除以2
        int newCapacity = oldCapacity + (oldCapacity >> 1);
// 转移数组元素, elementData原数组   newCapacity新数组长度 copyOf返回新数组
elementData = Arrays.copyOf(elementData, newCapacity);

算法案例

此部分的案例主要是对数组的排序算法,但是如果没有特殊要求,最好使用Arrays.sort方法,它的效率还是不错的,sort方法需要传入一个参数,数组对象,并且数组中的元素要实现排序接口Comparable,否则,sort方法并不知道如何对数组中元素排序。还有另一个办法,允许数组中元素可以不实现Comparable接口,但调用sort方法时不仅要传入数组对象,还需要额外传入一个自定义的排序器。无论如何,Arrays的sort方法自身并不知道如何对数组元素进行排序,它要么依赖数组元素自己排序,要么依赖外部的排序器。对于Java中的八大数据类型和String都已经实现了排序接口,所以对于这些数组还是挺方便的。如果是我们自定义的类如Student,就要自己设计如何排序了。

冒泡

冒泡排序是最基本的排序,要求必须掌握的排序算法。
冒泡排序是最简单的,但是效率最低的排序算法,它的原理是:
1.拿数组第1个元素和它后面的每一个元素进行比较,如果小于等于后面元素则不做交换,如果大于后面的元素则交换一次,直到最后一个元素,结果是数组最后一个元素是数组中最大的元素。
2.和第1次一样,一一比较,区别是已经知道最后一个元素是最大的元素,所以此次不用比较,少比较一次。
3.略

       //需要进行arr.length趟比较
        for(int i = 0 ;i<arr.length-1;i++){
            //第i趟比较
            for(int j = 0 ;j<arr.length-i-1;j++){
                //开始进行比较,如果arr[j]比arr[j+1]的值大,那就交换位置
                if(arr[j]>arr[j+1]){
                    int temp=arr[j];
                    arr[j]=arr[j+1];
                    arr[j+1]=temp;
                }
            }

        }

排序的算法还有:选择排序,插入排序,快速排序等。

重载

什么是重载呢?在一个类中,当两个方法的方法名相同,参数列表不同时,这两个方法就构成了重载。重载的必要条件是,方法名相同,参数列表不同,对于方法的返回值不做要求。
为什么需要重载呢?方法名相同,说明它们处理的业务应该是类似的,不同的是处理的对象略有不同,此时就需要重载,如果不重载也可以,就是给方法起不同的名称,但是,既然它们处理的事情类似,就不如给它们起同样的名称,只要参数列表的个数,顺序或类型不相同就可以,Java是允许这么做的。
重载是一个非常常见的现象,在Java的源码中比比皆是,有机会看源码时注意观察这个现象。
下面是简单的代码

  public void print(String msg){}
  public void print(int num){}

注意:参数列表不同,不是说参数名不同,编译器只看参数类型不看变量的名称。
print(String str1){}和print(String str2){}并不构成重载

继承和多态

继承可以使子类方便拥有父类的成员,使代码可以复用,使代码更好地维护。继承的关键字是extends
此处的知识较多,且经常出现在面试中。
继承不建议层次太多,否则类结构过于复杂。
继承打破了封装,如果一个类中的成员不可以被别的类调用时,但如果继承了该类,则可以访问本不能访问的成员。(在包和权限中再说明 )

对象初始化

class A{}
class B extends A{}

B b = new B(); 此时在内存中会先创建B父类A的对象new A()然后再new B(),并且在b对象中包含一个a对象。如果A还有父类的话,会先创建A的父类对象,依次类推。

方法重写

子类可以继承父类的方法,当子类也有同名的方法时,就会覆盖父类的方法,这种现象叫方法的重写。重写是有限制的:子类中方法的签名必须要和父类中的方法签名完全相同,即方法名、返回类型和方法参数列表必须相同,访问修饰符不能小于父类的。子类中重写的方法所能抛出的异常不能强于父类的(强是指异常的数量和类型不,异常后续再说明)

class A{
   protected void m1(String msg){}
}
class B extends A{
   /**
   * 访问修饰符可以是protected也可以是public,剩下的必须和A中的m1方法一样,除了参数名可以不同,方法体中的代码可以不同
   */
   public void m1(String msg){}
}

继承和属性

父类的属性如果不是private是可以继承过来的,但是无法被子类覆盖。

class A{
   protected int id=1;
   private String name = "father";
}
class B extends A{
   protected int id=2;
}   

B b = new B();
sout(b.id)结果是2。
sout(b.name)结果是"father" 。
这个不是覆盖,是隐藏了父类的属性,它的原理是:当通过b对象调用属性id时,在b对象内找到了id就返回,不再进一步查找,当通过b调用name时,因为b中没有,就往上找,找到了它包含的父类的属性name,返回该属性。

多态

由父类声明的变量指向它的子类,当指向不同的子类时,因为子类之间的差异,从而使该变量表现出不同的特性的现象叫做多态。
同一个行为(方法)具有不同表现形式的能力。

class A{
  protected int id = 1;
  protected void say(){
    sout("hello A");
   }
class B extends A{
  protected int id = 2;
  protected void say(){
    sout("hello B");
   }
class C extends A{
  protected int id = 3;
  protected void say(){
    sout("hello C");
   }       

A a = new B();
sout(a.id)结果是1,因为属性是无法覆盖的,实际上谁声明的变量,就是谁的属性。
a.say() 结果是hello B,因为say方法被重写了,就是覆盖了。
a = new C();
a.say() 结果是hello C,这就是多态,a的表现是多种形态的。

静态

static 类文件加载到JVM中时就初始化,只和类有关,和对象无关,可继承,不可覆盖。
静态方法不能访问非静态的成员。

抽象和接口

抽象是不具体,在父类中往往有些方法无法具体描述细节,就把该方法定义成抽象方法,具体如何实现细节由其子类的重写方法来实现。
没有实现细节的方法叫抽象方法,没有方法体,方法声明需要加修饰符abstract。
有了抽象方法的类就必须定义成抽象类,abstract class xxxx{} ,但是抽象类可以没有抽象方法。抽象类存在的意义就是为了继承,如果没有继承,抽象类将没有任何意义,因为抽象类无法实例化,无法创建对象。假设抽象类可以创建对象,可以实例化,那么这个对象调用抽象方法将会是矛盾的,因为抽象方法什么也不能做。

abstract class Father{
    public abstract void say();
}
class Son extends Father{
    public void say(){
       sout("say hello");
    }
}

利用抽象类和抽象方法可以完成一些设计模式,如模板模式:

public abstract class Car {
    protected void assemble(){
        engine();
        tyre();
     }
    protected abstract void engine();
    protected abstract void tyre();
}
class Benchi extends Car{
    @Override
    protected void engine() {
        sout("安装奔驰引擎");
    }

    @Override
    protected void tyre() {
        sout("安装奔驰轮胎");
    }
}
class Test{
    public static void main(String[] args) {
        Car benchi = new Benchi();
        benchi.assemble();
    }
}

super

补充super,super意思是超级的,在这儿主要是和父类有关。super要关注两个用法:
1.调用父类的构造方法
如果父类有默认构造方法,则可以不用super,但是,如果父类只有有参的构造方法,此时,在创建子类对象时,在子类的
构造方法中就要显示的调用super构造方法。
2.在子类方法中调用父类已经被重写的方法

public class Animal {
    protected String name = "Animal";
    protected void say(){
        System.out.println("Animal say...");
    }
    protected void test(){
        this.say();// ?1
        System.out.println(this.name);// ?2
    }
    public static void main(String[] args) {
        Animal animal = new Cat();
        animal.test();
    }
}
class Cat extends Animal{
    protected String name = "Cat";
    @Override
    public void say(){
        System.out.println("miao miao...");
    }
    @Override
    public void test(){
        this.say();// ?3
        super.say();// ?4
    }
}

以上代码是一段父子继承的代码,其中有关于继承时属性和方法如何处理的问题。这儿要说一个多态的问题,

Animal animal = new Cat();

此时的animal虽然指向了Cat的实例,但是它同时也是Animal的身份,所以,animal是无法调用Animal中不存在的方法和属性。它能调用的属性和方法要么是Animal自身的,要么是被Cat覆盖的(只有方法才能覆盖)。
假设Cat中没有对test方法重写(可以注释掉此方法),这时调用test是Animal中的test方法,test方法中两个问题各输出什么?

    protected void test(){
        this.say();// ?1
        System.out.println(this.name);// ?2
    }

?1:这儿的this.say()虽然写在父类中,父类的say方法已经被覆盖了,this.say()结果就是“miao miao…"
?2:这儿this.name得到的是animal,因为属性是无法覆盖的。
再来说一下,把子类的test方法放开,使其覆盖了父类的test方法,此时animal.test()调用的是Cat的test方法

    @Override
    public void test(){
        this.say();// ?3
        super.say();// ?4
    }

?3:调用的当然是cat的say方法“miao miao…”
?4:因为是super.say(),此时调用的是Animal中的say方法,super可以调用被子类覆盖的方法,super在此处代表了父类。

instanceof和强转

instanceof运算符是特殊的运算符,可以判断某个对象是否某个类的实例。
如果B是A的子类,则:
A obj = new B(); 赋值号= 左边是大类型,基本类型,右边是子类型,则可以自然转换,如:Chinese obj = new Shanxi();
if (obj instanceof B) 则B b = (B)obj;当检查到obj实际身份是B时,可以还原其身份到B类型,但此时obj的外在身份依然是A,所以转换时还是要加括号进行强转,强转的前提是类型正确,比如C也是A的子类,上面的obj就不能强转成C,会报类型转换错误的异常。

接口

接口是定义类的行为规范,只描述需要做什么,并不关心如何实现,实现的细节由接口的实现类来完成。Java8版本前,接口是没有普通方法的,全是抽象方法,Java8后,接口中也可以有普通方法,而不仅是抽象方法,只是普通方法要加default关键字,称此类方法为接口的默认方法。
接口的关键字是interface,它的实现类需要 implements关键字。
public interface A{
// public static final 可以省略,接口中定义的变量都是常量
public static final int NUM = 1;
// 接口中的方法默认是public abstract,所以这两个关键字可以省略
public abstract void m1();
public default void m2(){}
}
接口和抽象类的区别:
1.接口中的变量都是常量
2.接口中只有default方法和抽象方法
3.抽象类中可以有普通方法
4.抽象类有构造方法

包和权限

package,可以有效管理类,比如把功能相同的类放在一个包下,如:service包下放所有的业务类StudentService.java,ClazzService.java等
或者按模块管理,如:student包下放StudentBean.java,StudentService.java,StudentDao.java
目前按照习惯,项目代码按照功能分为三层结构:控制层,业务层,持久层。这三个层通常就是三个包:servlet,service,dao
随手做:建工程,建包

java.lang包,java.util包,java.io包,java.sql包

内部类

内部类:定义在一个类内部的类。

它可以在定义在一个类中的属性的区域,或方法中,或一个代码块中(if,for)

内部类可以有名称,可以没有名称(匿名内部类)

匿名内部类多用于抽象类或接口的实例化(抽象类和接口本身是不能创建对象的,不能实例的,但是可以通过匿名内部类间接实现)

内部类的优点:它可以具有类的功能,但是只限于当前类使用,不对外,否则就定义成一个外部的类。

内部类可以绕开Java的类的单继承,如果外部类继承了一个类,而此时还想继承另一个类,就让内部类来继承它。

两点:别人不用,自己用(所以是内部类);内部类可以定义成方法来使用,但方法有局限性,当一个方法完成不了时,需要定义成一个类,方法升级为内部类后,功能增强。可以组织代码,使的代码结构清晰。

分类 :

1.成员内部类

2.方法内部类

3.块内部类

4.匿名内部类

public class Outer {
    int id = 1;
    /**
     * 成员内部类
     */
    class Inner1{
        public void say(){
            System.out.println("Inner1.say");
        }
    }

    public static void main(String[] args) {
        Outer outer = new Outer();
        // 访问类的成员
        System.out.println(outer.id);
        // 创建内部类的实例,需要外部类的实例
        Outer.Inner1 inner1 = new Outer().new Inner1();
        inner1.say();
    }
}
/**
     * 静态成员内部类
     */
    static class Inner2{
        public void say(){
            System.out.println("Inner2.say");
        }
    }
main:
      Outer.Inner2 inner2 = new Outer.Inner2();
        inner2.say();

内部类可以访问外部类的数据(注意静态的使用,如果内部类是静态的,则情况复杂)

静态内部类只能访问外部类的静态数据

package c313.p4;

/**
 * copyright(c)2021 YCKJ.ALL rights Reserved
 * <p>
 * 描述:
 *
 * @author ychs
 * @version 1.0
 * @date 2021/3/13
 */
public class Outer {
    int id = 1;
    /**
     * 成员内部类
     */
    class Inner1{
        public void say(){
            System.out.println("Inner1.say");
            System.out.println("Outer.id=" + id);
        }
    }

    /**
     * 静态成员内部类
     */
    static class Inner2{
        public void say(){
            System.out.println("Inner2.say");
            //System.out.println("Outer.id=" + id);
        }
    }
    public void work(){
        /**
         * 方法内部类,只能在方法内部使用
         */
        class Inner1{
            public Inner1(){
                System.out.println("method work Inner1 created");
            }
            void work(){
                System.out.println("method Inner1.work");
            }
        }
        Inner1 inner1 = new Inner1();
        inner1.work();
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        // 访问类的成员
        System.out.println(outer.id);
        // 创建内部类的实例,需要外部类的实例
        Outer.Inner1 inner1 = new Outer().new Inner1();
        inner1.say();
        Outer.Inner2 inner2 = new Outer.Inner2();
        inner2.say();
        outer.work();
    }
}

package c313.p4;

/**
 * copyright(c)2021 YCKJ.ALL rights Reserved
 * <p>
 * 描述:
 *
 * @author ychs
 * @version 1.0
 * @date 2021/3/13
 */
public class Outer {
    int id = 1;
    /**
     * 成员内部类
     */
    class Inner1{
        public void say(){
            System.out.println("Inner1.say");
            System.out.println("Outer.id=" + id);
        }
    }

    /**
     * 静态成员内部类
     */
    static class Inner2{
        public void say(){
            System.out.println("Inner2.say");
            //System.out.println("Outer.id=" + id);
        }
    }
    public void work(){
        /**
         * 方法内部类,只能在方法内部使用
         */
        class Inner1{
            public Inner1(){
                System.out.println("method work Inner1 created");
            }
            void work(){
                System.out.println("method Inner1.work");
            }
        }
        Inner1 inner1 = new Inner1();
        inner1.work();
    }
    public void work2(){
        if(id >0 ){
            /**
             * 块内部类
             */
            class Inner1{
                public Inner1(){
                    System.out.println("if block Inner1 created");
                }
            }
            Inner1 inner1 = new Inner1();
        }
    }

    /**
     * 匿名内部类,一个没有名称的实现了IAnimal接口的类
     */
    IAnimal animal = new IAnimal() {
        @Override
        public void say() {
            System.out.println("匿名内部类的say方法");
        }
    };
    public static void main(String[] args) {
        Outer outer = new Outer();
        // 访问类的成员
        System.out.println(outer.id);
        // 创建内部类的实例,需要外部类的实例
        Outer.Inner1 inner1 = new Outer().new Inner1();
        inner1.say();
        Outer.Inner2 inner2 = new Outer.Inner2();
        inner2.say();
        outer.work();
        outer.work2();
        // animal是Outer类的一个成员,这个成员是匿名内部的实例
        outer.animal.say();
    }
}

以上是所有内部类的案例代码。

附录:

javadoc

javadoc -encoding utf-8 -charset utf-8 A.java


  1. // 按位取反
    int num = ~3;
    // 3原码:0000,0011
    // 取反后:1111,1100(这是补码,换成原码)
    // 补码-1->反码(取反)->原码
    // 1111,1100-1->1111,1011(取反)->1000,0100(-4)
    System.out.println(num);
    // 1000,0101(原)->1111,1010(反)->1111,1011(加1)补码
    num = -5;
    // 对-5的补码取反
    // 1111,1011->0000,0100(4)
    num = ~num;
    System.out.println(num);
    
    ↩︎
  2.  // 相当于2乘以2的3次方
    // 2:0000,0010.最后一位后有一个原点作为移位的基点
    // 左移:把0000,0010.向左移,右补零0001,0000.
    int num = 2<<3;
    System.out.println(num);
    // 先算-2的原码1000,0010,反码1111,1101,补码1111,1110
    // 1111,1110左移3位1111,0000(补)
    // 1111,0000(补)->1110,1111(-1得反码)->1001,0000(取反得原码-16)
    num = -2<<3;
    System.out.println(num);     
    
    ↩︎
  3. // 0001,0000.->0000,0010把数字向右移3位高位补0
    int num = 16 >> 3;
    System.out.println(num);
    // 原码:1001,0000->1110,1111(反码)->1111,0000(补码)
    // 1111,0000右移3位,高位补1。
    // 补:1111,1110->1111,1101(减1得反码)->1000,0010(原码-2)
    num = -16 >> 3;
    System.out.println(num);
    
    ↩︎
  4. // 正数的无符号右移和有符号右移没有区别,负数不同
    // 原码:1001,0000->1110,1111(反码)->1111,0000(补码)
    // 1111,0000右移3位,高位补0
    // 1111,1111,1111,1111,1111,1111,1111,0000
    // 0001,1111,1111,1111,1111,1111,1111,1110(536870910)
    int num = -16 >>> 3;
    System.out.println(num);      
    
    ↩︎
  5. byte n1 = 5;
    byte n2 = 6;
    // 5*6=30 说明变量在同一个表达式中在变化值
    int n3 = n1++ * n1++;
    System.out.println(n3);
    // 7 * 8=56
    n3 = ++n2 * ++n2;
    System.out.println(n3);     
    //------------------------------------------------------------------------------------------
     byte n1 = 5;
    byte n2 = 6;
    // 虽然+比*运算符低但++要先算
    int n3 = n1++ + n1++ * n1++;
    System.out.println(n3);             
    //-------------------------------------------------------------------------------------------
    byte b1 = 5;
    byte b2 = 6;
    // 5|6^7&4*7*5
    //010|0110^0111&240(11110000)=0111
    int num = b1++ | b2-- ^ ++b1 & --b2 * b1-- * ++b2;
    System.out.println(num);
    
    ↩︎
  6. byte b1 = 1;
    byte b2 = 2;
    byte b3 = 3;
    byte b4 = 4;
    // 先3&4 结果 ^ 2 结果 | 1=3
    int num = b1 | b2 ^ b3 & b4;
    System.out.println(num);
    //先2&1 结果^3 结果|4
    num = b4 | b3 ^ b2 & b1;
    System.out.println(num);        
    
    ↩︎

最后

以上就是忧伤外套为你收集整理的Java二运算符动态数组算法案例重载继承和多态静态抽象和接口superinstanceof和强转包和权限内部类附录:的全部内容,希望文章能够帮你解决Java二运算符动态数组算法案例重载继承和多态静态抽象和接口superinstanceof和强转包和权限内部类附录:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部