继承、接口、抽象方法
1 Runtime类 2 3 public class Demo3 { 4 public static void main(String[] args) { 5 //Runtime:运行时 6 //每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。 7 //可以通过 getRuntime 方法获取当前运行时。 8 9 //应用程序不能创建自己的 Runtime 类实例。 10 11 //获取运行时对象 12 Runtime runtime = Runtime.getRuntime(); 13 //获取的单位是字节 14 System.out.println(runtime.totalMemory()/1024./1024);//我们使用的总内容量 15 System.out.println(runtime.maxMemory()/1024./1024);//可以使用的最大内存量 16 System.out.println(runtime.freeMemory()/1024./1024);//当前空余的内存量 17 } 18 } 19 20 final关键字 21 package com.qianfeng.test; 22 23 public class Demo4 { 24 /* 25 * final:最终的,不可改变的. 26 * 可以修饰的内容: 27 * 1.类:不能有子类 28 * 2.成员方法:不能重写 29 * 3.成员变量:他的值是不能变了,成员变量必须先给一个值,并且值不能再改变 30 * 4.局部变量:他的值是不能变了,变成一个定值. 31 */ 32 } 33 34 class FuTest{ 35 final int age = 10;//final修饰的成员变量必须先给一个值,并且值不能再改变 36 public void test(){ 37 //age = 12; 38 final int height; 39 height = 3; 40 //height = 4;//当给定一个值之后,不能再改变值. 41 } 42 } 43 44 class ZiTest extends FuTest{ 45 //final修饰的成员变量不能重写 46 // public void test() { 47 // // TODO Auto-generated method stub 48 // super.test(); 49 // } 50 } 51 52 53 54 public class Demo5 { 55 //求圆的面积 56 public static void main(String[] args) { 57 Circle circle = new Circle(2); 58 double area = circle.getArea(); 59 System.out.println(area); 60 } 61 } 62 class Circle{ 63 double r; 64 final double PI = 3.14;//定值--符号常量 65 66 public Circle(double r) { 67 super(); 68 this.r = r; 69 } 70 71 public double getArea(){ 72 return PI*r*r; 73 } 74 } 75 76 //单例中的饿汉式 77 class SingleInstance{ 78 private static final SingleInstance singleInstance = new SingleInstance(); 79 private SingleInstance(){ 80 81 } 82 public static SingleInstance getInstance() { 83 return singleInstance; 84 } 85 } 86 87 抽象类和方法 88 89 90 public class Demo6 { 91 public static void main(String[] args) { 92 /* 93 * 方法的声明:没有方法体的方法 94 * 95 * abstract:抽象的 96 * 可以修饰的内容: 97 * 1.方法:抽象方法 98 * 2.类:抽象类 99 * 抽象类:在继承中,提取父类方法的时候,每个子类都有自己的具体实现方法,父类不能决定他们 100 * 各自的实现方法,父类就不管了.所以在父类中只写方法的声明,将方法的实现交给子类.在类中 101 * 只有方法声明的方法称为抽象方法,拥有抽象方法的类称为抽象类. 102 * 103 * 注意点: 104 * 1.抽象类不一定有抽象方法,但是有抽象方法的一定是抽象类. 105 * 2.继承了抽象类的子类一定要实现抽象方法,如果不实现就只能将自己也变成抽象的. 106 * 3.抽象类不能直接创建对象,必须通过子类实现,所以抽象类一定有子类 107 * 108 * 比较普通类与抽象类: 109 * 1.普通类可以直接创建对象 110 * 2.抽象类可以有抽象方法 111 * 112 * 不能与abstract同时存在的关键字 113 * 1.final:被final修饰的类不能有子类,方法不能重写,但是abstract必须有子类,必须重写 114 * 2.static:修饰的方法可以通过类名调用,abstract必须通过子类实现 115 * 3.private:修饰的方法不能重写,abstract必须重写 116 */ 117 //抽象类不能直接创建对象 118 //Person person = new Person(); 119 } 120 } 121 122 //抽象类--拥有抽象方法的类一定是抽象类 123 abstract class Person{ 124 String name; 125 //抽象方法---相当于指定了一个规则 126 public abstract void teach(); 127 } 128 129 //可以将子类变成抽象的,之后要想使用当前的类就必须再创建子类,因为抽象类不能直接创建对象. 130 class Teacher extends Person{ 131 //重写--写抽象方法的实现 132 public void teach() { 133 134 135 } 136 } 137 138 代码案例 139 140 public class Demo7 { 141 public static void main(String[] args) { 142 /* 143 * 求圆和矩形的面积 144 */ 145 //测试: 146 } 147 } 148 149 abstract class Shape{ 150 public abstract double getArea(); 151 } 152 153 class Circle1 extends Shape{ 154 double r; 155 final double PI = 3.14; 156 157 public Circle1(double r) { 158 super(); 159 this.r = r; 160 } 161 162 public double getArea() { 163 164 return PI*r*r; 165 } 166 } 167 168 class Rectangle extends Shape{ 169 double height; 170 double width; 171 172 public Rectangle(double height, double width) { 173 super(); 174 this.height = height; 175 this.width = width; 176 } 177 178 public double getArea() { 179 return height*width; 180 } 181 } 182 183 接口 184 /* 185 * 接口:interface 186 * 构成: 187 * interface 接口名字{ 188 * 接口的实现部分 189 * (默认是public static final)成员变量; 190 * (默认是public abstract)成员方法; 191 * } 192 * 193 * 一般接口中不写成员变量,只写方法--只写规则---方法列表 194 * 195 * 接口起作用的方式:让类去实现接口 196 * 类与类之间的关系--继承---extends 197 * 类与接口之间的关系---实现----implements 198 * 199 * 问题一:接口与父类可以同时存在吗? 200 * 答:可以 201 * 202 * 问题二:一个子类只能有一个父类,也只能有一个父接口吗? 203 * 答:不对,可以同时存在多个接口. 204 * 205 * 问题三:父类与接口的功能如何分配? 206 * 答:一般父类中放的是主要功能,接口中放的是额外的功能.接口作为父类的补充 207 * 208 * 问题四:接口可以直接创建对象吗? 209 * 答:不可以,因为接口默认是抽象的 210 * 211 * 问题五:接口与接口之间可以有关系吗?如果有,是什么关系? 212 * 答:可以有,是多继承的关系. 213 * 214 * 问题六:当一个类实现的接口中出现了相同的方法,子类中实现方法的时候会不会混淆? 215 * 答:不会,接口中的方法都是抽象的,要通过子类写具体的实现.我们在调用方法的时候,最终看的功能,而功能只有一份. 216 * 217 * 接口功能总结:让java从单继承间接的实现了多继承.扩充了原来的功能. 218 * 219 * 了解: 220 * 从jdk1.7之后,接口中可以有方法的实现,但是方法必须是被static或者default修饰的. 221 */ 222 223 interface Inter1{ 224 int age = 3;//默认前面是public static final,所以成员变量必须先给一个值 225 public void play();//默认就是抽象的 226 } 227 228 interface Inter2{ 229 public void show(); 230 } 231 232 //接口Inter3同时继承了两个接口 233 interface Inter3 extends Inter1,Inter2{ 234 235 } 236 237 //这里是继承了Object类,同时实现了两个接口,接口之间用,隔开 238 class Dog extends Object implements Inter1,Inter2{ 239 240 public void play() { 241 242 } 243 244 public void show() { 245 // TODO Auto-generated method stub 246 247 } 248 } 249 250 package com.qianfeng.test; 251 252 public class Demo8interface { 253 //1.在jdk1.7的接口中可以写方法的实现,方法必须是default或static的 254 //2.接口还是不能直接创建对象,要通过子类 255 /* 256 * 接口的子类重写方法注意事项 257 * 如果一个类实现两个接口,这两个接口同时有相同的抽象方法,在类中只需要重写一次这个方法。 258 如果接口中有default修饰的方法不需要重写。 259 如果两个接口里的方法名相同都是default方法,里面的方法体不同,在类中需要重写该方法。 260 如果两个接口中方法名,参数都相同的方法,一个接口是抽象方法,另一个是default修饰有方法体。这时该类也必须重写该方法。 261 */ 262 public static void main(String[] args) { 263 //一个类有一个接口的情况 264 265 // //讲解Test6 266 // Test6 test1 = new Test6(); 267 // test1.run(); 268 // test1.eat();//调用父类的defalut方法,可以通过子类的引用调用 269 // //接口中static类型的方法,必须使用当前方法所在的接口名字去调用 270 // inter5.bark(); 271 272 273 274 //一个类有两个接口的情况 275 276 Test5 test = new Test5(); 277 test.run(); 278 //两个接口的同名方法,两个都是default类型的 279 test.eat(); 280 281 //子类的静态方法可以与父类的相同,但是方法在调用的使用各自调用各自的 282 inter5.bark(); 283 //如果两个接口中只有一个有default方法,不需要重写,可以直接使用 284 test.song(); 285 286 Test5.bark(); 287 288 //两个接口中的同名方法,一个是default类型的(有实现),一个是抽象的 289 test.play(); 290 } 291 } 292 293 interface inter5{ 294 public void run(); 295 296 default public void song() { 297 System.out.println("song"); 298 } 299 default public void eat(){ 300 System.out.println("default"); 301 } 302 303 static public void bark(){ 304 System.out.println("static"); 305 } 306 307 default public void play() { 308 System.out.println("play"); 309 } 310 } 311 312 interface inter6{ 313 public void run(); 314 default public void eat(){ 315 System.out.println("default1"); 316 } 317 318 static public void bark(){ 319 System.out.println("static1"); 320 } 321 322 public void play(); 323 } 324 325 class Test6 implements inter5{ 326 327 328 // 329 public void run() { 330 System.out.println("Test6"); 331 332 333 } 334 335 //default只能放在接口中 336 //如果当前接口中有一个default方法,不需要重写,可以直接使用 337 //比如现在的eat方法 338 339 //子类的静态方法可以与父类的相同,但是方法在调用的时候各自调用各自的 340 static public void bark(){ 341 342 System.out.println("static"); 343 } 344 345 } 346 347 class Test5 implements inter5,inter6{ 348 349 //如果两个接口中有相同的抽象方法,只需要重写一次 350 public void run() { 351 System.out.println("run"); 352 353 } 354 355 356 357 358 //如果两个接口中有相同的都有default实现的方法,我们必须要重写 359 //在重写方法中可以同时对两个父接口的调用,也可以只调用其中一个 360 public void eat() { 361 // TODO Auto-generated method stub 362 inter6.super.eat();//调用inter1中的方法 363 inter5.super.eat();//调用inter中的方法 364 365 //再写自己的功能 366 System.out.println("Test-eat"); 367 } 368 369 //如果两个接口中有两个同名的方法,一个是default实现的方法,一个是抽象方法,我们必须要重写 370 //在重写方法中可以同时对两个父接口的调用,也可以调用一个 371 public void play() { 372 inter5.super.play(); 373 System.out.println(""); 374 } 375 376 377 //子类的静态方法可以与父类的相同,但是方法在调用的时候各自调用各自的 378 static public void bark(){ 379 380 System.out.println("substatic"); 381 } 382 383 } 384 385 package com.qianfeng.test; 386 387 public class Demo9 { 388 /* 389 * 实例:防暴犬,搜救犬,导盲犬都去工作,中间还有一个导盲驴也要干活儿,导盲犬和导盲驴都要学习导盲技术 390 * 391 * 抽象类,抽象方法,接口,继承 392 */ 393 } 394 395 abstract class 犬{ 396 public abstract void work(); 397 } 398 399 class 防暴犬 extends 犬{ 400 401 public void work() { 402 System.out.println("防爆"); 403 404 } 405 } 406 407 class 搜救犬 extends 犬{ 408 409 public void work() { 410 System.out.println("搜救"); 411 412 } 413 } 414 415 interface Inter{ 416 public void study(); 417 } 418 419 class 导盲犬 extends 犬 implements Inter{ 420 @Override 421 public void work() { 422 System.out.println("导盲"); 423 424 } 425 426 @Override 427 public void study() { 428 System.out.println("学习导盲技术"); 429 430 } 431 } 432 433 class 导盲驴 implements Inter{ 434 @Override 435 public void study() { 436 System.out.println("学习导盲技术"); 437 438 } 439 } 440 441 package com.qianfeng.test; 442 /* 443 * Object类: 444 */ 445 public class Demo10 { 446 /* 447 * 实例:根据轮子的个数比较两辆车 448 */ 449 public static void main(String[] args) { 450 Car car1 = new Car(3); 451 Car car2 = new Car(4); 452 boolean b = car1.comWithWheels(car2); 453 System.out.println(b); 454 //默认的equals方法的比较规则是比较两个对象的地址 455 //我们可以通过重写equals方法达到自己指定规则的目的. 456 boolean b1 = car1.equals(car2); 457 System.out.println(b1); 458 459 //hashCode()获取是当前对象的哈希码值--直接拿到的是十进制的 460 System.out.println(car1.hashCode());//31168322 461 System.out.println(car2.hashCode());//17225372 462 463 //得到十六进制的数 464 System.out.println(Integer.toHexString(car1.hashCode()));//1db9742 465 466 //toString(),默认打印的是包名+类名+@+十六进制的哈希值 467 System.out.println(car1.toString());//com.qianfeng.test.Car@1db9742 468 System.out.println(car1);//默认执行的是toString() 469 470 //了解: 471 //getClass():获取的是当前对象的字节码文件 472 //字节码文件:一个类只有一个 473 //字节码文件本身就是一个对象 474 //字节码文件对象对应的类是Class 475 Class class1 = car1.getClass(); 476 System.out.println(class1);//字节码文件对象 class com.qianfeng.test.Car 477 //拼成默认的toString 478 System.out.println(class1.getName()+"@"+Integer.toHexString(car1.hashCode()));//com.qianfeng.test.Car@1db9742 479 } 480 } 481 482 class Car{ 483 int wheels; 484 public Car(int wheels) { 485 super(); 486 this.wheels = wheels; 487 } 488 public boolean comWithWheels(Car car){ 489 return wheels>car.wheels; 490 } 491 492 //重写equals方法,自己制定比较规则 493 public boolean equals(Object obj) {//多态 obj = new Car(4) ,就是用父类的引用指向子类的对象. 494 //向下转型-多态中的知识,从高类型转成低类型 495 Car car = (Car)obj; //car = new Car(4) 496 return wheels<car.wheels; 497 } 498 499 //重写toString---目的:可以更加方便的查看当前对象的属性信息 500 public String toString() { 501 return "Car [wheels=" + wheels + "]"; 502 } 503 504 505 506 }