1、数组排序之选择法排序和冒泡排序?
选择法排序原理:数组第一位和后续位置数值比较,最大或最小的调换位置后放在第一位;依次比较将第二大或小的值调换位置后放在第二位置;代码如下:
for (int j = 0; j < a.length-1; j++) {for (int i = j+1; i < a.length; i++) {if(a[i]<a[j]){ int temp = a[j];a[j] = a[i];a[i] = temp;}}}
冒泡法排序原理:数组相邻两个arr[i] 和arr[i+1]进行比较后将最大或最小的放在最后,循环比较后,最后一位是最大或最小的数值。代码如下
for (int j = 0; j < a.length; j++) {for (int i = 0; i < a.length-j-1; i++) {if(a[i]>a[i+1]){ int temp = a[i+1];a[i+1] = a[i];a[i] = temp;}}}
2、二维数组的分配空间及赋值: int[][] b=new int[2][3];表示该二维数组是有两个长度为3的一维数组组成,未初始化;int[][] b=new int[][]{ {1,2,3},{2,3,4} }
3、数组操作:Arrays是针对数组的工具类,可以进行 排序,查找,复制填充等功能。 大大提高了开发人员的工作效率。
数组复制方法:使用system.arrayCopy 方法,如System.arraycopy(src, srcPos, dest, destPos, length)将源数组数据复制到目标数组;使用Arrays.copyOfRange((src, srcPos, dest, destPos, )的返回值就是复制获取的数组;具体数组方法操作见 http://how2j.cn/k/array/array-arrays/516.html
4、引用:声明一个非基本类型的变量后,那么这个变量叫做引用。如使用new Hero()创建一个对象后怎么访问这个对象,就需要通过“=”等于号将引用指向该对象,如Hero h1=new Hero(); 引用前的Hero表示这个变量h1是Hero类型的。
5、多个引用可以指向的是一个对象,一个引用同时只能指向一个对象如 Hero garen=new Hero(); 和garen=new Hero(); 会冲突。注意:每次实例化一个对象时,系统会分配一块内存地址给这个对象,而系统默认是根据内存地址来检测是否是同一个对象,所以就算是同一个类里实例化出来的对象它们也不会相等。如:
Hero h1=new Hero();Hero h2=new Hero();System.out.println(h1.equals(h2)); //false,因为实例化的对象分配在不同的内存地址
6、Java类使用extend关键词实现继承类。方法的重载指的是方法名一样,但是参数类型不一样。重载方法过多时可以使用可变数量的参数,如public void attack(Hero ...heros),在方法里,使用操作数组的方式处理参数heros即可。
public class ADHero extends Hero {public void attack() {System.out.println(name + " 进行了一次攻击 ,但是不确定打中谁了");}public void attack(Hero h1) {System.out.println(name + "对" + h1.name + "进行了一次攻击 ");}public void attack(Hero h1, Hero h2) {System.out.println(name + "同时对" + h1.name + "和" + h2.name + "进行了攻击 ");}public static void main(String[] args) {ADHero bh = new ADHero();bh.name = "赏金猎人";Hero h1 = new Hero();h1.name = "盖伦";Hero h2 = new Hero();h2.name = "提莫";bh.attack(h1);bh.attack(h1, h2);}}
7、构造方法理解:通过一个类创建一个对象的过程叫做实例化,实例化是通过构造方法实践的。什么是构造方法?构造方法名和类名一致,但没有返回类型,实例化一个对象时必调用构造方法。如下
public class Hero extends Person {public Hero() { //无返回类型System.out.println("这是Hero类的构造方法");}public static void main(String[] args) {int[] a= {11,22,321,32,355};Hero h1=new Hero(); //实例化对象会调用后构造方法}
}
注意:类的构造方法不写的话,会默认提供一个无参构造方法。一旦提供了有参的构造方法,那么默认的无参的构造方法就没有了;和普通的构造方法一样,构造方法也可以重载。
8、java中this和this(), 在java中this指当前对象。在一个构造方法中调用另一个构造方法可以使用this(); 如下
public Hero(String name) { //无返回类型System.out.println("这是Hero类的构造方法,名字是:"+name);}
public Hero(String name,int age) { //无返回类型this(name); //构造方法中可以使用this调用另一个构造方法System.out.println("年龄是:"+age);}
9、变量包括基本类型和类类型,参数也是变量,所以传参分为基本类型传参和类类型传参。总结来说变量是基本类型则叫变量,如int a=12;a是变量,通过等号进行赋值;如果变量不是基本类型而是类类型,如Hero h1=new Hero(); h1是类类型的,叫引用,通过等号指向实例对象;
10、Package把相近的类划在一个包下,使用同包类的其他类直接使用就可以,使用不同包下的类则需要使用import引入。
11、类与类之间的关系:
成员变量有四种修饰符
private 私有的
package/friendly/default 不写
protected 受保护的
public 公共的
以Hero为例
自身:指的是Hero自己
同包子类:ADHero这个类是Hero的子类,并且和Hero处于同一个包下
不同包子类:Support这个类是Hero的子类,但是在另一个包下
同包类: GiantDragon 这个类和Hero是同一个包,但是彼此没有继承关系
其他类:Item这个类,在不同包,也没有继承关系的类
概括就是private修饰的成员变量只能被本身类所访问,default修饰(默认)的成员变量只能被自身和同包的类访问,protected修饰的成员变量可以被自身或同包类或子类访问,public修饰的变量可以被任何类访问。
使用技巧:属性通常使用private封装起来;方法一般使用public便于调用;会被子类继承的的方法,通常使用protected;作用范围最小原则就是能用private就用private,不行就网上default》protected》public
参考网址:http://how2j.cn/k/class-object/class-object-modifier/295.html#nowhere
12、单例模式:又叫做 Singleton模式,指的是一个类,在一个JVM里,只有一个实例存在。
饿汉式单例模式原理是通过私有化构造函数使外部无法实例化对象,再通过在类内部实例化一个该对象赋值给类属性(静态属性在内存上使唯一的),在通过提供静态方法来访问该静态属性,代码示例如下:
public class GiantDragon { //私有化构造方法使得该类无法在外部通过new 进行实例化private GiantDragon(){} //准备一个类属性,指向一个实例化对象。 因为是类属性,所以只有一个 private static GiantDragon instance = new GiantDragon(); //public static 方法,提供给调用者获取12行定义的对象public static GiantDragon getInstance(){return instance;}
}
懒汉式单例模式的不同是只有在getInstance的时候才会创建示例,如下:
//准备一个类属性,用于指向一个实例化对象,但是暂时指向nullprivate static GiantDragon instance;//public static 方法,返回实例对象public static GiantDragon getInstance(){//第一次访问的时候,发现instance没有指向任何对象,这时实例化一个对象if(null==instance){instance = new GiantDragon();}//返回 instance指向的对象return instance;}
public static void main(String[] args) {//通过new实例化会报错// GiantDragon g = new GiantDragon(); //只能通过getInstance得到对象 GiantDragon g1 = GiantDragon.getInstance();GiantDragon g2 = GiantDragon.getInstance();GiantDragon g3 = GiantDragon.getInstance(); //都是同一个对象System.out.println(g1==g2);System.out.println(g1==g3);}
区别、使用技巧(什么时候使用饿汉式单例模式,什么时候使用懒汉式单例模式?)
饿汉式是立即加载的,无论是否使用到这个对象都会加载,如果构造函数中写了性能消耗较大、占时较长的代码,比如建立和数据的连接,那么就会在启动的时候稍微有些卡顿;懒汉式是延迟加载的方式,只有在使用的时候才会加载,并且有线程安全的考量。使用懒汉式,在启动的时候,会感觉到比饿汉式略快,因为并没有做对象的实例化。 但是在第一次调用的时候,会进行实例化操作,感觉上就略慢。看业务需求,如果业务上允许有比较充分的启动和初始化时间,就使用饿汉式,否则就使用懒汉式
13、对象转型,类型转换指的是改变引用所指向的对象类型。通常Hero h=new Hero(); 中h引用的引用类型是Hero,new Hero()创建的对象是Hero对象,引用类型和对象类型是一样的。 那么引用类型和对象类型不一样的情况下会怎么样?向上转型(子类可以转父类),如Hero h = new Hero();ADHero ad = new ADHero(); h = ad; 这里h引用重新指向了ADHero对象类型。判断类型转换能否成功,可以尝试将右边的当做左边的来用看是否行的通,如ADhero当hero英雄是可以的,强制转换如ad=(ADhero)h;
注意:没有继承关系的类进行转换是不可以的,抛出异常 ClassCastException 类型转换异常。如ad = (ADHero) ap;会失败。 实现类转换成接口是可以的,如AD adi=new ADhero();因为实现类ADhero对象是完全实现了接口中的方法的,所以当接口用是可以的。
h1 instanceof Hero 可以判断h1引用指向的对象类型是否为Hero,个人理解是:类型转换改变的引用的指向,并没有改变引用类型。
package charactor;public class TestHero extends Hero {public static void main(String[] args) {Hero h=new Hero();TestHero th=new TestHero();h=th; //类型转换:h引用重新指向子类对象TestHero,所以使用h引用调用的方法,调用的是TestHero对象的方法h.test(); //输出 TestHero类的方法th.test(); //输出 TestHero类的方法System.out.println(h instanceof TestHero ); //instanceof判断左侧是否是右侧的实例对象System.out.println(h instanceof Hero ); //true,因为引用指向的对象继承了Hero对象}public void test() {System.out.println("TestHero类的方法");}}
14、继承重写:子类可以继承父类的对象方法,在继承后重复提供该方法,就叫做方法的重写或override
另外重载发生在同一个类(如构造方法带参和不带参),重写发生在不同类(如多态的实现)。
15、多态:操作符的多态体现在“+”加号上,加号两侧是整形则两侧数字相加,如果加号两侧任意一个是字符串则加号代表字符串连接。多态是指同一个类型调用同一个方法,却能呈现不同的状态。可以理解类型转换和继承重写结合后形成多态代。码如下:
Item i1= new LifePotion(); //这里引用类型都是父类类型,指向到不同的子类实例上,所以输出不一样Item i2 = new MagicPotion();System.out.print("i1 是Item类型,执行effect打印:");i1.effect();System.out.print("i2也是Item类型,执行effect打印:");i2.effect();
多态形成的条件是:父类(接口)引用指向子类对象,调用的方法有重写。
参考网址:http://how2j.cn/k/interface-inheritance/interface-inheritance-polymorphic/315.html
16、隐藏:方法的重写是子类覆盖父类的对象方法。隐藏就是子类对父类的类方法(静态方法)的重写。Hero h =new ADHero(); h.battleWin(); 在battleWin()方法是类方法时,注意父类的引用无论指向哪个对象都执行的类方法仍然是父类的类方法。。
package charactor;public class Hero {public static void test() {System.out.println("Hero类的静态方法");}
}
package charactor;public class TestHero extends Hero {public static void main(String[] args) {// TODO Auto-generated method stubTestHero.test(); //继承父类后对父类的静态方法的重写叫做隐藏Hero.test();Hero th=new TestHero(); //父类类型的引用指向子类对象,会对象转型为父类Hero类型th.test(); //但是调用的还是引用类型父类的静态方法!!}public static void test() {System.out.println("继承Hero类的后对test静态方法进行覆盖叫做隐藏");}}
17、实例化子类,父类的构造方法一定会被调用,而且父类的构造方法会被优先调用。如果实例化子类时带参数,就需要用到super(参数)来调用父类的有参构造方法,如下:
public Hero(String name) { //无参显示构造方法
System.out.println("Hero类的有参构造方法");
this.name=name;
}
public APhero(String name) {super(name); //注意位置必须在构造方法的第一行System.out.println("APhero类的有参构造方法,需要使用super关键字");}public static void main(String[] args) {APhero ap1=new APhero("teemo");}
Super关键字:还可以使用通过super调用父类的属性,如this.moveSpeed 和super.moveSpeed。
18、Object类是所有类的父类,声明一个类的时候默认是继承了Object类的,
- Object类有toString()方法返回当前对象的字符串表达;
- finalize()方法是当一个对象没有任何指向的时候就会触发垃圾回收机制,垃圾回收时JVM会调用该方法。
- equals()方法判断两个对象内容是否一致。“==”不是Object的方法,但是可以判断两个引用是否指向一个对象。
- hashCode() 方法返回一个对象的哈希值。
- Object还提供线程同步相关方法wait()、notify()、notifyAll()。getClass()会返回一个对象的类对象,属于高级内容。
19、抽象类:在类中声明一个方法,该方法没有实现主体,是一个“空”方法,这个方法就叫做抽象方法,使用“abstract”修饰,当一个类中有抽象方法时,这个类就叫做抽象类。子类可以通过继承抽象类实现不同的方法。抽象类可以不包含抽象方法,但是抽象类不能被实例化。
抽象类和接口都定义了不包含方法体的方法,那么有什么其他的区别?区别一:子类只能继承一个抽象类但可以实现多个接口。区别二:接口中声明的属性只能是public static final的,而抽象类中可以定义public、defalut、protected、private类型的、静态和非静态属性、final和非final的属性。
20、内部类:包括非静态内部类和静态内部类、匿名类、本地类。语法: new 外部类().new 内部类()。所以非静态内部类的实例必须建立在一个外部类对象的基础上的。
21、匿名类是指在声明一个类的同时实例化它,通常要使用一个接口或一个抽象类必须创建一个子类,为了快速使用,可以直接实例化一个抽象类,并当场实现其抽象方法。既然实现了抽象方法,那么这就是一个新的类,只是个类没有命名,这样的类就叫做匿名类。如下:
public abstract void attack(); //该抽象方法的抽象类
Hero h = new Hero(){ //实例化抽象类时直接实现抽象方法//当场实现attack方法public void attack() {System.out.println("新的进攻手段");}};
内部类和匿名类的区别是:内部类声明在外部类成员的位置,而本地类和匿名类是声明在代码块里面的,可以是主方法或for循环的代码块里面的。
public static void main(String[] args) {//与匿名类的区别在于,本地类有了自定义的类名class SomeHero extends Hero{ //内部本地类public void attack() {System.out.println( name+ " 新的进攻手段");}}SomeHero h =new SomeHero();h.name ="地卜师";h.attack();
}
22、接口默认方法是JDK8新特性,指的是接口也可以提供具体方法了,而不像以前,只能提供抽象方法。Mortal 这个接口,增加了一个默认方法 revive,这个方法有实现体,并且被声明为了default
package charactor;public interface Mortal {public void die();default public void revive() {System.out.println("本英雄复活了");}
}
优点:假设没有默认方法这种机制,那么如果要为Mortal增加一个新的方法revive,那么所有实现了Mortal接口的类,都需要做改动。但是引入了默认方法后,原来的实现类,不需要做任何改动,并且还能得到这个默认方法。通过这种手段,就能够很好的扩展新的类,并且做到不影响原来的类
23、UML图的理解和使用
理解:UML-unified module language 统一建模语言,可以很方便的描述类的属性、方法、以及类和类之间的关系。
使用:其中修饰符#表示protected ,修饰符+表示 default,方法有下划线表示是构造方法,方法是斜体表示是抽象方法,带箭头的实线表示继承,带箭头的虚线表示实现接口。
更多资源或实战项目详细可以了解:http://how2j.cn/k/interface-inheritance/interface-inheritance-practise/679.html?p=29570