1 - &
与 &&
的区别:
&
:不管左边是true
还是false
,右端都会进行运算;&&
:当左端为false
时,右端不再进行运算;- 即在
与
运算时,前面为false
,即可判断该条件为false
了,后面没必要再算了 ----建议使用&&
.
2 - |
与 ||
的区别:
|
:不管左端,右端照算;||
:左端为true
时,右端不用算(最终结果已经可以确定为true
了);- 建议用
||
3 - java中内存的基本结构:
4 - this
关键字的使用:
- 1 - 当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须添加
this
来表明该变量的类成员;- 2 - 在任意方法内,如果使用当前类的成员变量或成员方法可以在其前面添加
this
,增强程序的阅读性;- 3 - this可以作为一个类中,构造器相互条用的特殊格式;
public Person(String name){ this(); //调用本类中的无参构造方法 this.name = name; } public Person(String name, int age){ this(name); //调用有一个参数的构造方法 this.age = age; }
5 - this
和super
的区别:
No. | 区别点 | this | super |
---|---|---|---|
1 | 访问属性 | 访问本类中的属性,如果本类中没有此属性,则从父类中继续查找 | 访问父类中的属性 |
2 | 调用方法 | 访问本类中的方法 | 直接访问父类中的方法 |
2 | 调用构造器 | 调用本类构造器,必须放在构造器的首行 | 调用父类构造器,必须放在子类构造器的首行 |
4 | 特殊 | 表示当前对象 | 无此概念 |
6 - 权限修饰符的区别:
- private :无法被子类继承,也无法被外部类调用;
- protected :显示的表示可以被子类继承;
- public : 可以被外部类直接调用;
7 - java
中的多态:
Person
父类,有eat()
,walk()
;Man
和 Woman
为继承了 Person
类的子类,并且都重写了eat()
和walk()
方法,
另外,Woman
类中有一个自己的方法,即shooping()
Man m = new Man(); m.eat(); m.walk(); System.out.println(); //*【子类对象的多态性】:父类的引用指向子类对象 Person p1 = new Man(); //向上转型 //虚拟方法调用:通过父类的引用指向子类对象的实体,当调用方法时,执行的是子类重写父类的方法 p1.eat(); p1.walk(); Person p2 = new Woman(); p2.eat(); p2.walk(); Woman w = (Woman)p2; //向下转型 w.shooping();
补充:instanceof
:类型判断
//格式:对象p instanceof 类A if(p1 instanceof Woman){ //如果p1是Woman类型,则可以转型 Woman w1 = (Woman)p1; w1.shooping(); }
8 - static
修饰属性(类变量):
1.由类创建的所有对象,都共用这一个属性
2.当其中一个对象对此属性进行修改,会导致其他对象对此属性的一个调用。vs 实例变量(非static
变量修饰的属性
3.类变量随着类的加载而加载的,而且独一份
4.静态的变量可以直接通过“类.类变量”的形式来调用
5.类变量的加载要早于对象。所以当有对象以后,可以“类.类变量”使用。但是“类.实例变量”是不行的。
6.类变量存在与静态域中。
class SportMan{ //实例变量(随着对象的创建而被加载的) String name; int age; //类变量 static String nation; }
8 - static
修饰方法(类方法):
1.随着类的加载而加载,在内存中也是独一份
2.可以直接通过“类.类方法”的方式调用
3.内部可以调用静态的属性或静态的方法,而不能调用非静态的属性或方法。反之,非静态的方法可以调用静态的属性或静态的方法
>静态的方法内是不可以有this或super关键字的!
注:静态的结构(static的属性、方法、代码块、内部类)的生命周期要早于非静态的结构,被回收也要晚于非静态的结构
>可以简单记住:加了static
的方法和变量,可以不new
一个对象而直接通过类.方法名
或类.变量名
来调用,例如:
class Black{ Test.bianliang; //直接调用,而不需要new一个 Test.fangfa(); //直接调用,而不需要new一个 } Class Test{ public static int bianliang = 666; public static void fangfa(){ System.out.println("测试方法"); } }
9 - 单例模式
【推荐阅读博客】:https://blog.csdn.net/goodlixueyong/article/details/51935526
1.解决的问题:使得一个类只能创建一个对象。
2.如何实现?见如下4步
//饿汉式 public class TestSingleton{ public static void main(String[] args){ Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getINstance(); System.out.println(s1 == s2); //比较两个对象的引用是否一样 //而equal()用来比较两个对象是否一样 } } //只能创建Singleton的单个实例 class Singleton{ //1.私有化构造器,使得在类的外部不能够调用次构造器 private Singleton(){ } //2.在类的内部创建一个类的实例 private static Singleton instance = new Singleton(); //3.私有化此对象,通过公共的方法来调用 //4.此公共的方法,只能通过类来调用,因为设置为static的,同时类的实例也必须为static声明的 public static Singleton getInstance(){ return instance; } }
ture
//懒汉式:可能存在线程安全问题 public class TestSingleton1{ public static void main(String[] args){ Singleton1 s1 = Singleton1.getInstance(); Singleton1 s2 = Singleton1.getINstance(); System.out.println(s1 == s2); } } class Singleton1{ //1.私有化构造器 private Singleton1(){ } //2.在类的内部创建一个类的实例,并使其为私有和静态的 private static Sintleton1 instance = null; //3.返回对象 public static Singleton1 getInstance(){ if(instance == null){ instance = new Singleton1(); } return instance; } }
10 - final修饰
- 1.final修饰类:这个类就不能被继承;
- 2.final修饰方法:这个方法不能被子类重写;
- 3.final修饰属性:此属性就是一个常量,一旦初始化,就不能再赋值。习惯上常量有大写字母表示;
11 - java集合
Collection
接口:
Set
:元素无序、不可重复的集合;List
:元素有序,可重复的集合;
Map接口:具有映射关系“key-value”的集合;
12 - java
中的接口
- 1.接口可以看作是一个特殊的抽象类。是常量与抽象方法的一个集合,不能包含变量、一般的方法。
- 2.接口是没有构造器的;
- 3.接口定义的就是一种功能。 此功能可以被类所实现(
implements
);比如:class CC extends DD implements AA
- 4.实现接口的类,必须要重写其中的所有的抽象方法,方可实例化。若没有重写,则仍为抽象类;
- 5.类可以实现多个接口。 -----
java
中类的的继承是单继承的;- 6.接口与接口之间也是继承的关系,而且可以实现多继承。
- <5、6是面试的重点>
13 - 集合的使用
Collection
接口:
List
接口:存储有序的,可以重复的元素 ---- 相当于“动态”数组;
》添加进List集合中的元素(或对象)所在的类一定要重写equals()
方法;
ArrayList
(主要的实现类)LinkedList
(链表形式的实现类,更适用于频繁的插入、删除操作)Vector
(古老的实现类、线程安全的,但效率要低于ArrayList
)
Set
接口:存储无序的,不可重复的元素 ---- 相当于高中的集合概念
》添加进Set集合中的元素所在的类一定要重写equals()
和hashCode()
方法;
HashSet
(主要的实现类)LinkedHashSet
(是HashSet
的子类,当我们遍历集合元素时,是按照添加进去的顺序实现的)TreeSet
(可以按照添加进集合中的元素的制定属性进行排序)
- 要求
TreeSet
添加进的元素必须是同一个类的!- 两种排序方式:
- 自然排序:
- ①要求添加进
TreeSet
中的元素所在类implementS Comparable
接口- ②重写
compareTo(Object obj)
,在此方法内指明按照元素的哪个属性进行排序- ③向
TreeSet
中添加元素即可,若不实现此接口,会报运行时异常
- 定制排序:
- ①创建一个实现
Comparator
接口的实现类的对象,在实现类中重写Comparator
的方法- ②在此
compare()
方法中指明按照元素所在类的哪个属性进行排序- ③将此实现
Comparator
接口的实现类的对象作为形参传递给TreeSet
的构造器中- ④向
TreeSet
中添加元素即可,若不实现次接口,会报运行时异常
- 》要求重写的
compareTo()
或者compare()
方法与equals()和hashCode()
方法保持一致。
Map
接口:存储“键-值”对的数据 ---- 相当与高中的“函数 y = f(x)”
- key是不可重复的,使用Set存放。value可以重复,使用Collection来存放的。一个key-value构成一个entry(Map.Entry),entry使用Set来存放
- HashMap:主要的实现类,可以添加null键,null值
- LinkedHashMap:是HashMap的子类,可以按照添加进Map的顺序实现遍历
- TreeMap:需要按照key所在类的制定属性进行排序,要求key是同一个类的对象,对key考虑使用自然排序 或 定制排序
- HashTable:是一个古老的实现类,线程安全的,不可以添加进null键,null值;不建议使用。
- 子类:Properties:重用来处理属性文件(如数据库的配置文件)
14 - java
多线程
//使用实现Runnable接口的方式,售票 /** * 此线程会存在线程安全问题 * 2.如何来解决线程的安全问题? * 必须让一个线程操作共享数据完毕后,其他线程才有机会参与共享数据的操作 * * 3.java如何实现线程的安全:线程的同步机制 * * 方式一:同步代码块 * synchronized(同步监视器){ * //需要被同步的代码(即为操作共享数据的代码) * } * 1.共享数据:多个线程共同操作的同一个数据(变量) * 2.同步监视器:由一个类的对象来充当。哪个线程获取此监视器,谁就执行大括号里被同步的代码。俗称:锁 * 要求:所有的线程必须共用同一把锁! * 注:在实现的方式中,考虑同步的话,可以使用this来充当锁。但是在继承的方法中,慎用this * * 方式二:同步方法 * 将操作共享数据的方法声明为synchronized。即此方法为同步方法,能够保证当其中一个线程执行此方法时, * 其他线程在外等待直至此线程执行完此方法。 * * @author hasee * */ //实现的方式 //加锁实现同步(同步代码块) class Window1 implements Runnable { int ticket = 100; Object obj = new Object(); public void run() { while (true) { synchronized (obj) { if (ticket > 0) { System.out.println(Thread.currentThread().getName() + ":" + ticket--); } else { break; } } } } } //实现的方式(通过静态共享变量保证多个线程修改的是同一个变量) class Window2 implements Runnable { static int ticket = 100; public void run() { while (true) { if (ticket > 0) { try { Thread.currentThread().sleep(10); //将多线程的错误放大 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + ticket--); } else { break; } } } } //同步的方式(通过继承的方式来实现多线程) class Window3 extends Thread { static int ticket = 100; static Object obj = new Object(); //静态的监视器,避免不同进程使用不同的监视器,造成无法同步的安全问题 public void run(){ while(true){ synchronized (obj) { if(ticket > 0){ try { Thread.currentThread().sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + ticket--); } } } } } //同步的方法(通过接口实现) class Window4 implements Runnable { int ticket = 100; //共享数据 public void run() { while (true) { show(); } } //将该方法声明为synchronized方法 public synchronized void show(){ if (ticket > 0) { try { Thread.currentThread().sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + ":" + ticket--); } } } public class TestWindow1 { public static void main(String[] args) { // 方式一:3个Thread共享一个Window1类对象 Window1 w = new Window1(); Thread t1 = new Thread(w); Thread t2 = new Thread(w); Thread t3 = new Thread(w); t1.start(); t2.start(); t3.start(); // 方式二:三个Window2类对象,各自分别对应了3个Thread // 这种方式必须保证共享的变量(即共享资源)为静态的,否则出错 // Window2 w21 = new Window2(); // Window2 w22 = new Window2(); // Window2 w23 = new Window2(); // Thread t21 = new Thread(w21); // Thread t22 = new Thread(w22); // Thread t23 = new Thread(w23); // t21.start(); // t22.start(); // t23.start(); } }