Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int
:
int x;
x = 10;
В этом примере переменная x является int
, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.
Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:
Integer num;
num = new Integer(10);
Первая строка объявляет переменную с именем num
, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer
является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».
Во второй строке ключевое слово new
используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num
присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования .
(точка).
Exception
, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num
. Перед созданием объекта вы получите NullPointerException
. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.
Например, вы можете имеют следующий метод:
public void doSomething(SomeObject obj) {
//do something to obj
}
В этом случае вы не создаете объект obj
, скорее предполагая, что он был создан до вызова метода doSomething
. К сожалению, этот метод можно вызвать следующим образом:
doSomething(null);
В этом случае obj
имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException
, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.
Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething
может быть записано как:
/**
* @param obj An optional foo for ____. May be null, in which case
* the result will be ____.
*/
public void doSomething(SomeObject obj) {
if(obj != null) {
//do something
} else {
//do something else
}
}
Наконец, Как определить исключение & amp; причина использования Трассировки стека
Bitarray был лучшим ответом, который я нашел, когда у меня недавно была подобная потребность. Это - расширение C (настолько быстрее, чем BitVector, который является чистым Python), и хранит его данные в фактическом битовом поле (таким образом, это - в восемь раз больше памяти, эффективной, чем numpy булев массив, который, кажется, использует байт на элемент.)
Я использую двоичные побитовые операторы!, & |, ^,>>, и < <. они работают действительно хорошо и реализованы непосредственно в базовом C, который находится обычно непосредственно на используемом оборудовании.
Представьте каждое из своих значений как питание два:
testA = 2**0
testB = 2**1
testC = 2**3
Затем для устанавливания верного значения:
table = table | testB
Для установки лжи значения:
table = table & (~testC)
Для тестирования на значение:
bitfield_length = 0xff
if ((table & testB & bitfield_length) != 0):
print "Field B set"
Роют немного глубже в шестнадцатеричное представление, если это не имеет смысла Вам. Это в основном, как Вы отслеживаете свои булевы флаги во встроенном приложении C также (при ограничении памяти).
Пакет BitVector может быть тем, в чем Вы нуждаетесь. Это не встроено к моей установке Python, но легкое разыскать на сайте Python.
https://pypi.python.org/pypi/BitVector для текущей версии.
NumPy имеет интерфейс массива модуль, который можно использовать для создания битового поля.
Если Ваше битовое поле коротко, можно, вероятно, использовать модуль структуры . Иначе я рекомендовал бы своего рода обертка [приблизительно 111] модуль массива .
кроме того, ctypes модуль действительно содержит битовые поля , но я никогда не использовал его сам. Принцип "качество на риск покупателя" .
Я должен был иметь дело с некоторыми управляющими словами / флаги в протоколе связи и моем фокусе были то, что редактор дает мне предложения имен флага и переходов к определению флагов с "F3". Код ниже удовлетворяет требования тезисов (Решение с ctypes @nealmcb, к сожалению, не поддерживается индексатором PyCharm сегодня.). Приветствующиеся предложения:
""" The following bit-manipulation methods are written to take a tuple as input, which is provided by the Bitfield class. The construct
looks weired, however the call to a setBit() looks ok and the editor (PyCharm) suggests all
possible bit names. I did not find a more elegant solution that calls the setBit()-function and needs
only one argument.
Example call:
setBit( STW1.bm01NoOff2() ) """
def setBit(TupleBitField_BitMask):
# word = word | bit_mask
TupleBitField_BitMask[0].word = TupleBitField_BitMask[0].word | TupleBitField_BitMask[1]
def isBit(TupleBitField_BitMask):
# (word & bit_mask) != 0
return (TupleBitField_BitMask[0].word & TupleBitField_BitMask[1]) !=0
def clrBit(TupleBitField_BitMask):
#word = word & (~ BitMask)
TupleBitField_BitMask[0].word = TupleBitField_BitMask[0].word & (~ TupleBitField_BitMask[1])
def toggleBit(TupleBitField_BitMask):
#word = word ^ BitMask
TupleBitField_BitMask[0].word = TupleBitField_BitMask[0].word ^ TupleBitField_BitMask[1]
""" Create a Bitfield type for each control word of the application. (e.g. 16bit length).
Assign a name for each bit in order that the editor (e.g. PyCharm) suggests the names from outside.
The bits are defined as methods that return the corresponding bit mask in order that the bit masks are read-only
and will not be corrupted by chance.
The return of each "bit"-function is a tuple (handle to bitfield, bit_mask) in order that they can be
sent as arguments to the single bit manipulation functions (see above): isBit(), setBit(), clrBit(), toggleBit()
The complete word of the Bitfield is accessed from outside by xxx.word.
Examples:
STW1 = STW1Type(0x1234) # instanciates and inits the bitfield STW1, STW1.word = 0x1234
setBit(STW1.bm00() ) # set the bit with the name bm00(), e.g. bm00 = bitmask 0x0001
print("STW1.word =", hex(STW1.word))
"""
class STW1Type():
# assign names to the bit masks for each bit (these names will be suggested by PyCharm)
# tip: copy the application's manual description here
def __init__(self, word):
# word = initial value, e.g. 0x0000
self.word = word
# define all bits here and copy the description of each bit from the application manual. Then you can jump
# to this explanation with "F3"
# return the handle to the bitfield and the BitMask of the bit.
def bm00NoOff1_MeansON(self):
# 0001 0/1= ON (edge)(pulses can be enabled)
# 0 = OFF1 (braking with ramp-function generator, then pulse suppression & ready for switching on)
return self, 0x0001
def bm01NoOff2(self):
# 0002 1 = No OFF2 (enable is possible)
# 0 = OFF2 (immediate pulse suppression and switching on inhibited)
return self, 0x0002
def bm02NoOff3(self):
# 0004 1 = No OFF3 (enable possible)
# 0 = OFF3 (braking with the OFF3 ramp p1135, then pulse suppression and switching on inhibited)
return self, 0x0004
def bm03EnableOperation(self):
# 0008 1 = Enable operation (pulses can be enabled)
# 0 = Inhibit operation (suppress pulses)
return self, 0x0008
def bm04RampGenEnable(self):
# 0010 1 = Hochlaufgeber freigeben (the ramp-function generator can be enabled)
# 0 = Inhibit ramp-function generator (set the ramp-function generator output to zero)
return self, 0x0010
def b05RampGenContinue(self):
# 0020 1 = Continue ramp-function generator
# 0 = Freeze ramp-function generator (freeze the ramp-function generator output)
return self, 0x0020
def b06RampGenEnable(self):
# 0040 1 = Enable speed setpoint; Drehzahlsollwert freigeben
# 0 = Inhibit setpoint; Drehzahlsollwert sperren (set the ramp-function generator input to zero)
return self, 0x0040
def b07AcknowledgeFaults(self):
# 0080 0/1= 1. Acknowledge faults; 1. Quittieren Störung
return self, 0x0080
def b08Reserved(self):
# 0100 Reserved
return self, 0x0100
def b09Reserved(self):
# 0200 Reserved
return self, 0x0200
def b10ControlByPLC(self):
# 0400 1 = Control by PLC; Führung durch PLC
return self, 0x0400
def b11SetpointInversion(self):
# 0800 1 = Setpoint inversion; Sollwert Invertierung
return self, 0x0800
def b12Reserved(self):
# 1000 Reserved
return self, 0x1000
def b13MotorPotiSPRaise(self):
# 2000 1 = Motorized potentiometer setpoint raise; (Motorpotenziometer Sollwert höher)
return self, 0x2000
def b14MotorPotiSPLower(self):
# 4000 1 = Motorized potentiometer setpoint lower; (Motorpotenziometer Sollwert tiefer)
return self, 0x4000
def b15Reserved(self):
# 8000 Reserved
return self, 0x8000
""" test the constrution and methods """
STW1 = STW1Type(0xffff)
print("STW1.word =", hex(STW1.word))
clrBit(STW1.bm00NoOff1_MeansON())
print("STW1.word =", hex(STW1.word))
STW1.word = 0x1234
print("STW1.word =", hex(STW1.word))
setBit( STW1.bm00NoOff1_MeansON() )
print("STW1.word =", hex(STW1.word))
clrBit( STW1.bm00NoOff1_MeansON() )
print("STW1.word =", hex(STW1.word))
toggleBit(STW1.bm03EnableOperation())
print("STW1.word =", hex(STW1.word))
toggleBit(STW1.bm03EnableOperation())
print("STW1.word =", hex(STW1.word))
print("STW1.bm00ON =", isBit(STW1.bm00NoOff1_MeansON() ) )
print("STW1.bm04 =", isBit(STW1.bm04RampGenEnable() ) )
Это распечатывает:
STW1.word = 0xffff
STW1.word = 0xfffe
STW1.word = 0x1234
STW1.word = 0x1235
STW1.word = 0x1234
STW1.word = 0x123c
STW1.word = 0x1234
STW1.bm00ON = False
STW1.bm04 = True
Вам следует взглянуть на модуль bitstring , который недавно достиг версии 2.0. Двоичные данные компактно хранятся в виде байтового массива и могут быть легко созданы, изменены и проанализированы.
Вы можете создавать объекты BitString
из двоичных, восьмеричных, шестнадцатеричных, целых чисел (с прямым или обратным порядком байтов), строк , байты, числа с плавающей запятой, файлы и т. д.
a = BitString('0xed44')
b = BitString('0b11010010')
c = BitString(int=100, length=14)
d = BitString('uintle:16=55, 0b110, 0o34')
e = BitString(bytes='hello')
f = pack('<2H, bin:3', 5, 17, '001')
Затем вы можете анализировать и изменять их с помощью простых функций или нотации срезов - не нужно беспокоиться о битовых масках и т. д.
a.prepend('0b110')
if '0b11' in b:
c.reverse()
g = a.join([b, d, e])
g.replace('0b101', '0x3400ee1')
if g[14]:
del g[14:17]
else:
g[55:58] = 'uint:11=33, int:9=-1'
Также существует концепция битовой позиции, так что вы можете рассматривать его как файл или поток, если это вам полезно. Свойства используются для различных интерпретаций битовых данных.
w = g.read(10).uint
x, y, z = g.readlist('int:4, int:4, hex:32')
if g.peek(8) == '0x00':
g.pos += 10
Плюс есть поддержка стандартных побитовых бинарных операторов, упаковки, распаковки, порядка байтов и многого другого. Последняя версия предназначена для Python 2.7 и 3.x, и хотя это чистый Python, он достаточно хорошо оптимизирован с точки зрения памяти и скорости.